Continuously summon commitments

After extensive searching online, I am still grappling with this particular issue.

Currently, I'm developing an Angular service for an Ionic application. This service's primary function is to download an image. In traditional JavaScript, I would typically tackle this problem using recursive calls to prevent repetition in my code.

I attempted to implement the solution using promises to familiarize myself with the concept, but I've encountered some challenges along the way.

Take a look at the following code snippet:

public getBgForName = (name: string) => {
  name = name.toLowerCase();
  var instance = this;
  var dir = this.file.dataDirectory;
  return new Promise(function (fulfill, reject) {
    instance.file.checkDir(dir, name).then(() => {
      // directory exists. Is there a bg file?
      dir = dir + '/' + name + '/';
      instance.file.checkFile(dir, 'bg.jpg').then(() => {
        console.log('read file');
          fulfill(dir + '/' + 'bg.jpg')
      }, (err) => {
        // dl file and re-call
        console.log('needs to download file!')
        instance.transfer.create().download(encodeURI('https://host.tld/'+name+'/bg.jpg'), dir + 'bg.jpg', true, {})
          .then((data) => {
            return instance.getBgForName(name).then((url) => {return url});
          }, (err) => {
            console.log(err)
          })
      })
    }, (err) => {
      // create dir and re-call
      instance.file.createDir(dir, name, true).then(() => {
          instance.getBgForName(name).then((url) => {fulfill(url)});
      })
    })

  });
}

When invoked, the promise never seems to fully resolve. Upon reading this article, it appears that the issue lies in the correct passing of resolved promises within the chain - causing the resolution only up to a certain level, but not all the way to the top. Evidently, when the conditions mentioned below are met, the promise resolves correctly:

  • The directory is already created

  • The file is already downloaded

Hence, I suspect that the return statements somehow disrupt the connection here, preventing the promise from resolving after the initial recursive call.

What is the appropriate method for recursively calling a promise while ensuring that the original caller receives the result once it becomes available?

Edit: Per David B.'s suggestion, I will outline the desired outcome. The objective of this code segment is to have a function that processes a list of items. Each item corresponds to a background image stored on a server, which is then cached locally. The rationale behind utilizing recursive calls is to consistently return a URL to the local filesystem housing the image, regardless of its current status (downloaded or pending). The workflow is as follows:

  • Create a directory for the current item
  • Download the file into this directory
  • Return a local URL pointing to the downloaded file

Subsequent calls should merely retrieve the image directly from disk (after confirming its existence), without any additional downloads.

Answer №1

After discovering the advantages of async / await over promises and being impressed by its cleaner syntax, I decided to refactor my code using async / await. The revised code may not be perfect but it now looks like this:

public fetchBackgroundForName = async (name: string) => {
  name = name.toLowerCase();
  let instance = this;
  let dir = this.file.dataDirectory;

  try{
    await instance.file.checkDir(dir, name)
    dir = dir + name + '/';
    try{
      await instance.file.checkFile(dir, 'bg.jpg')
      return dir + 'bg.jpg';
    }catch(err) {
      // download file
      await instance.transfer.create().download(encodeURI('https://host.tld/'+name+'/bg.jpg'), dir + 'bg.jpg', true, {})
      return this.fetchBackgroundForName(name);
    }
  }catch(err) {
    // no need to handle errors here as failure to write to the app's local storage indicates a serious issue.
    await instance.file.createDir(dir, name, true)
    return this.fetchBackgroundForName(name);
  }
}

This refactored code now functions as intended.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Attempt to periodically load remote JSON data (error: Origin is not permitted by Access-Control-Allow-Origin)

My goal is to regularly load a .json file containing some information, and here is the code I have come up with: var updateIBEX35 = function () { var ibexText = document.getElementById("IBEX"); let url = 'https://www2.ecobolsa.com/js/data/i3 ...

What is the correct way to implement async RedisJSON functions?

I'm currently facing an issue with properly typing the redis node package. For instance, let's consider the basic code snippet for a simple JSON.GET operation. import * as redis from 'redis'; const client = redis.createClient(); async f ...

What are the steps to troubleshoot a Vue application?

I've encountered an issue with a code snippet that retrieves JSON data from a RESTful API. The code only displays the .container element and reports that the items array is empty, even though no errors are being shown. I attempted to debug the problem ...

Utilizing the adapter design pattern in Angular with TypeScript for enhancing a reactive form implementation

I've been struggling to understand how to implement the adapter pattern in Angular6. Despite reading numerous articles and tutorials, I still can't quite grasp the concept. Could someone provide some insights on this topic? Essentially, I have a ...

Is it possible for me to utilize a validation function to display error messages within a specific span id tag?

document.getElementById("button1").addEventListener("click", mouseOver1); function mouseOver1(){ document.getElementById("button1").style.color = "red"; } document.getElementById("button2").addEventListener("click", mouseOver); function mous ...

The Google Maps JavaScript API is failing to load

While constructing a website that utilizes the Google Maps JS API, I encountered an issue where the map remains blank without any errors appearing in the Google Chrome Console. HTML code: <div id="map-container-5" class="z-depth-1" style="height: 200 ...

Having trouble retrieving values from a feature file in a Typescript implementation with the Cucumber Framework

Having trouble accessing values from a feature file in Typescript while using the Cucumber Framework tool Protractor. How do I retrieve these Example values in my typescript method within the When block? Here is the code for the Feature file: Feature: Na ...

The CKEditor value is set to the result of the dropdown selection

I need to implement a dropdown feature on my form where the options correspond to titles of content in my database. Once an option is selected, I want the corresponding content to display in a CKEditor field. I'm attempting to achieve something simil ...

Using Bootstrap Modal with Jquery: Detected 2 elements on the DOM that share the same id, but thankfully all IDs are distinct

I have integrated Bootstrap 4 into my website, and I am facing an issue with having two different modal types on a single page. I am using Ajax to populate the content of these modals, and while the forms in each modal are distinct, they share some similar ...

The request method 'PUT' is not currently supported

Currently, I am working on a project that involves springboot, angularjs, and restful services. Here is my REST controller: @RequestMapping(value="/updatestructure/{ch}", method = RequestMethod.PUT) public @ResponseBody Structurenotification updateStruct ...

Dependency injection in Angular 2 pipes

Greetings everyone! I'm a newcomer to angular 2 and currently trying my hand at creating a custom pipe/filter. However, I've encountered an issue when attempting to inject the pipe I created inside app.ts as shown in the image linked here. Here ...

Guide to automatically updating a table with AJAX requests

My task involves utilizing AJAX to request a random string consisting of 10 numbers from an asp page. The numbers must be delimited by "||" and displayed in a table format. The table is designed to showcase only the top 10 results, with each new row addin ...

What is the best way to set up a server in React using Express or HTTP?

I am currently in the process of developing a web application using react js. In order to create a server for my client within the project, I have decided to utilize either express or http. Here is the code snippet that I attempted: import React from " ...

An unexpected runtime error occurred due to a SyntaxError: the JSON input abruptly ended during the authentication process with the next-auth module

Encountering an Unhandled Runtime Error SyntaxError: Unexpected end of JSON input when trying to SignIn or SignOut with authentication credentials. The error is puzzling as it displays the popup error message, but still manages to register the token and s ...

Unable to display Vue image within v-for loop

I'm facing an issue with rendering images from an array of objects. Even though the paths to the images are correct, the images are not displaying. I've been following a tutorial at which suggests specifying the image URLs as links. I've t ...

CORB prevented the loading of a cross-origin response

I'm encountering an issue where I am not receiving a response from an API call using Angular 4 service. However, the same call is working in the browser. The error message that I am facing is: Cross-Origin Read Blocking (CORB) blocked cross-origin res ...

The loading spinner remains active (ng-show = loading) even after submitting the form. It should be disabled once the data has been received

I'm struggling with a scope variable issue. I have implemented a loading spinner that appears when the ng-show property is set to true after the submit button is clicked on my contact form. The goal is to set the ng-show property to false after the fo ...

Tips for utilizing mergeWith with Subjects in an Angular application

Objective: Creating a Combined Filter with 3 Inputs to refine a list Conditions: Users are not required to complete all filters before submission The first submit occurs when the user inputs data Inputs are combined after more than one is provided Appro ...

Mastering Data Labels in ng2-chart: A step-by-step guide

Once again, I find myself battling my Angular and JavaScript challenges, each question making me feel a little less intelligent. Let me walk you through how I got here. In my most recent project, I wanted to enhance the user experience by incorporating sl ...

The TypeScript error message states, "The property 'value' is not found on 'EventTarget'."

When working with TypeScript and React, I encountered an error in the following code snippet: Property 'value' does not exist on type 'EventTarget'. import React, { Component } from 'react'; class InputForm extends React ...