Exploring nested promises in TypeScript and Angular 2

I have a method called

fallbackToLocalDBfileOrLocalStorageDB
, which returns a promise and calls another method named getDBfileXHR, also returning a promise.

In the code snippet provided, I am unsure whether I need to use 'resolve()' explicitly or if resolving getDBfileXHR will automatically resolve

fallbackToLocalDBfileOrLocalStorageDB
.

Although I have commented out the then().catch() parts, I am uncertain about whether I should remove them entirely.

fallbackToLocalDBfileOrLocalStorageDB() {
        return new Promise(function (resolve, reject) {
            if (this.storageService.get('prodata') === null) { 
                if (this.connectionStatus.f() !== 'online') {
                } else {
                    this.sendErrorEmail("BL: online but falling back to local proDB", 10);
                }
                console.log('...falling back to local proBD.jsonp.');
                return this.getDBfileXHR('proDB.jsonp');
                    // .then(function () {
                    //    console.log('...falling back to local proBD.jsonp succeeded.');
                    //    resolve();
                    // })
                    // .catch(, function () {
                    //    console.log('...error, shit.');
                    //    reject();
                    // });

EDIT showing the full nested functions, with partially fixed code:

import { Injectable } from '@angular/core';
...

export class UpdateProDB {

    constructor(
        ) {
    }   


    get() {
        var debugOptionUseLocalDB = 0,
        prodata = [],
        serverAttempts = 0;     return new Promise((resolve, reject) => {
            if (debugOptionUseLocalDB) {
                return this.fallbackToLocalDBfileOrLocalStorageDB();
            }
            if (this.connectionStatus.f() === 'online') {
                console.log("Fetching DB from the server:");
                return this.getDBfileXHR(this.dbUrl(), serverAttempts)
                .then(function (data) { 
                    console.log('-normal XHR request succeeded.');

                    resolve(data);
                })
                .catch((reason)=> {
                    if (typeof serverAttempts !== "undefined") serverAttempts++;
                    console.log('on passe dans le catch, serverAttempts = ', serverAttempts)
                    if (serverAttempts < 2) {
                        return this.getDBfileXHR(this.dbUrl(), serverAttempts)
                        .then(function () { 
                            console.log('-basic XHR request succeeded.');

                        })
                        .catch(function (){
                            console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");

                        })
                    } else {
                        console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
                        return this.fallbackToLocalDBfileOrLocalStorageDB()
                        .then((data)=>{
                            resolve(data);
                        })
                        .catch((reason)=> {
                            reject(reason);
                        });
                    }
                });
            });
    }   

    getDBfileXHR(url, serverAttempts) {
        return new Promise((resolve, reject) => {
            var request = new XMLHttpRequest();
            request.open("GET", url, true);             
            request.onload = ()=> {
                if ( (request.readyState === 4) && ( (request.status >= 200 && request.status <= 299) || request.status === 304 || request.status === 0) ) {
                    console.log('-we get response '+request.status+' from XHR in getDBfileXHR');

                    var jsonText = request.responseText.replace("callback(", "").replace(");", ""); 

                    if (jsonText === '') {
                        console.error('-error');

                        reject({
                            status: request.status,
                            statusText: request.statusText
                        });

                    } else {
                        var parsedJson;
                        try {
                            parsedJson = JSON.parse(jsonText);
                        } catch (e) {
                            resolve(request.response);
                        }
                    }
                };
                request.onerror = ()=> {
                    reject({
                        status: request.status,
                        statusText: request.statusText
                    });
                };
                console.log("sending request.send()");
                request.send();

            });
    }   


    fallbackToLocalDBfileOrLocalStorageDB() {
        return new Promise((resolve, reject) => {
            if (this.storageService.get('prodata') === null) { 
                if (this.connectionStatus.f() !== 'online') {

                } else {
                    this.sendErrorEmail("BL: online but falling back to local proDB", 10);
                }
                console.log('...falling back to local proBD.jsonp.');
                return this.getDBfileXHR('proDB.jsonp', undefined)
                .then(function (data) {
                    console.log('...falling back to local proBD.jsonp succeeded.');
                    resolve(data);
                })
                .catch((reason)=> {
                    console.log('...error, shit.');
                    reject(reason);
                });
            } else { 
                resolve();
            }
        });
    }   

Answer №1

Start using arrow functions => instead of the traditional function to maintain the context of this keyword:

fallbackToLocalDBfileOrLocalStorageDB() {
        return new Promise((resolve, reject) => {
            if (this.storageService.get('prodata') === null) { 
                if (this.connectionStatus.f() !== 'online') {
                } else {
                    this.sendErrorEmail("BL: online but falling back to local proDB", 10);
                }
                console.log('...falling back to local proBD.jsonp.');
                return this.getDBfileXHR('proDB.jsonp');
                      .then(function (data) {
                         console.log('...falling back to local proBD.jsonp succeeded.');
                        resolve(data);
                     })
                      .catch((reason)=> {
                         console.log('...error, stuff.');
                        reject(reason);
                      });

You can access your data like this:

fallbackToLocalDBfileOrLocalStorageDB().then((data)=>{
   console.log(data);
})

Answer №2

An executor function is the argument passed to new Promise(). It is responsible for either resolving or rejecting the promise.

Attempting to return another Promise from this executor function will not work as explained on MDN, stating that "The return value of the executor is ignored."

This indicates that using an inner Promise in the manner you are trying won't be effective; instead, you must explicitly resolve or reject the promise as shown in your commented code.

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

Unexpected behavior observed with field alignment

I've been attempting to align the field in an Angular HTML page, but it's not working out as I expected. Here's how the HTML file looks: <div id="report-prj-search"> <div class="dx-fieldset flex-column"> <div class="fle ...

The function for batch insertion only functions with Postgresql and SQL Server databases

I am a beginner in JavaScript and I am currently working on creating a new restaurant. I have come across a code snippet that inserts a relation into a join-table: await newRestaurant.$relatedQuery('tags', trx).relate(tagIds); Is it not possible ...

Ensuring that a service is completely initialized before Angular injects it into the system

When Angular starts, my service fetches documents and stores them in a Map<string, Document>. I use the HttpClient to retrieve these documents. Is there a way to postpone the creation of the service until all the documents have been fetched? In ot ...

Tips for utilizing innerHTML in TypeScript code within an Angular 2 application

Is there a way to utilize innerHTML from TypeScript code in Angular 2 RC4? I'm facing an issue: I need to dynamically add precompiled HTML code when a specific button is clicked. For instance: TypeScript code private addHTML() { // not sure how ...

strategies for chaining together multiple observables with varying data types and operations

Hey everyone! I'm facing a situation where I have a form with multiple select types, and the options for these inputs are coming from an API. I then take the data emitted from the HTTP request observable and feed it into my FormGroup, and everything i ...

Angular 8: ngx-socket-io changes the connection URL while in production mode

One issue arises when running the application in production mode. In development mode, the socket client successfully connects to http://localhost:3002/socket.io/?EIO=3&transport=polling&t=N4--_Ms. However, in production mode, the URL changes to ht ...

Prevent a React component from unnecessarily re-rendering after a property has been set

I am working on a react component that displays a streaming page similar to the one shown in this image. Here is a snippet of the code : const [currentStream, setCurrentStream] = useState<IStream>(); const [currentStreams] = useCollectionData<ISt ...

Which RxJS operators necessitate unsubscription?

It can be confusing to know which operators in RxJS must be unsubscribed from to prevent subscription leaks. Some, like forkJoin, complete automatically, while others, such as combineLatest, never complete. Is there a comprehensive list or guideline availa ...

Angular Unit Test: Received 1 argument instead of the expected 3

Currently, I am in the process of unit testing an Angular application. This is my first time venturing into Angular Unit Testing. To save time, I downloaded the angular app from here. As a beginner in Unit Testing, I watched some informative videos on the ...

The correct way to update component state when handling an onChange event in React using Typescript

How can I update the state for 'selectedValues' in a React component called CheckboxWindow when the onChange() function is triggered by clicking on a checkbox? export const CheckboxWindow: React.FC<Props> = props => { const [selected ...

Having trouble with errors when trying to implement react-router-v6 with typescript

Having trouble with my code and receiving the following error: "Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element | DocumentFragment'. Type 'null' is not assignable to type 'Element | ...

What is the reason behind tsc disregarding the include and exclude options in tsconfig.json?

I am facing an issue with my tsconfig.json file: { "compilerOptions": { "target": "ES6", "lib": [ "DOM", "ES6" ] }, "include": [ "src/server/**/*&q ...

Steps to fix the issue of 'Property 'foo' lacks an initializer and is not definitely assigned in the constructor' while utilizing the @Input decorator

What is the proper way to initialize a property with an @Input decorator without compromising strict typing? The code snippet below is triggering a warning: @Input() bar: FormGroup = new FormGroup(); ...

What is the process for including an object in an http.post request?

My contact object needs to be included in the http.post method. I'm struggling with where exactly to pass this contact parameter. Can you provide guidance on how to modify my code accordingly and also share any relevant links related to the http.post ...

The variable is accessed before it is initialized in the context of Next.js and Server Actions

Currently, I am utilizing the new Data Fetching feature in Next JS to retrieve data from an API and store it in a variable named 'contact.' However, I am facing the issue of receiving an error message stating that "variable 'contact' is ...

Having trouble with a single GET request not functioning properly on Safari due to an Authorization issue in Angular 6

I've encountered this issue in several locations, yet haven't found a clear solution. Only one GET request is showing as unauthorized (401), but when I check the debugger, everything seems to be fine and all other requests are functioning properl ...

Struggling with integrating Axios with Vue3

Can someone assist me in figuring out what is going wrong with my Axios and Vue3 implementation? The code I have makes an external call to retrieve the host IP Address of the machine it's running on... <template> <div id="app"> ...

Updating row values in an Angular table

I have a reusable table with the [cellData]="row" attribute to populate each cell on the table (see sample table in the screenshot). My question is, how can we replace the null values on the template with "---" so that instead of displ ...

Dynamic React Gallery with Interactive Image Picker

Looking to develop a new photo management application as an alternative to Google Photos, with a focus on displaying and selecting images in a user-friendly way. Currently using the react-grid-gallery library for this purpose. Here is my current implement ...

Error: The @use directive must come before any other rules in Angular

Error message: Issue: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js): Error Details: HookWebpackError: Module build failed (from ./node_modules/sass-loader/dist/cjs.js) ...