Solving the issue of interconnected promises in Angular services

I am utilizing a DynamoDB service within my Angular project which returns a promise through a series of promises. This process involves retrieving a subId from Cognito and then passing that subId to a DynamoDB get query:

async getUserObject(): Promise<any> {
    var promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            let response; 
            let cognitoUser = this.cognitoUtil.getCurrentUser();
            cognitoUser.getSession(function (err, session) {
            if (err)
                console.log("UserParametersService: Couldn't retrieve the user");
            else {
                //Here we're fetching the subId and returning a promise 
                cognitoUser.getUserAttributes(
                    function getSubId(err, result) {
                        let cognitoSubIdPromise = new Promise((resolve,reject) => {
                            setTimeout(() => {
                                if (err) {
                                    reject('error');
                                } else {
                                    let response: any = result[0].getValue();
                                    resolve(response);
                                }
                            }, 1000);
                        });
                        //Once we've resolved the subId from Cognito we can plug it into our DynamoDB query
                        cognitoSubIdPromise.then((val) => {
                            let clientParams:any = {
                                params: {TableName: environment.ddbTableName}
                            };
                            if (environment.dynamodb_endpoint) {
                                clientParams.endpoint = environment.dynamodb_endpoint;
                            }
                            var DDB = new DynamoDB(clientParams);
                            var getParams = {
                                TableName: environment.ddbTableName,
                                Key: {
                                    'userId' : {S: val.toString()},
                                }
                            };
                            //Executing the query
                            DDB.getItem(getParams, 
                                function (err, result) {
                                    if (err){
                                        console.log(err)
                                    } else {
                                        console.log("DynamoDBService got user object: " + JSON.stringify(result));
                                        response = result;
                                    }
                                }
                            );
                        });
                    });
                }
            });
          console.log("Async Work Complete");
          resolve(response);
        }, 1000);
      });
      return promise;
}

In another user-login service, I am ensuring that a Cognito function callback directing us to the home page of the app after login is only triggered once the db query from my DynamoDB service is completed

databaseDynamo.getUserObject().then((data => {
                console.log("this is the resolved data", data);
                console.log("getUserObject function execution done!");
                callback.cognitoCallback(null, session);
           }));

The console log for resolved data always shows as undefined, and the cognito callback function executes before the data has a value. How can I delay the triggering of the cognitoCallBack function until I have the necessary data?

Answer №1

Your current issue arises from resolving inappropriately

async fetchUserDetails(): Promise < any > {
  var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      let response;
      let cognitoUser = this.cognitoUtil.getCurrentUser();
      cognitoUser.getSession(function (err, session) {
        if (err)
          console.log("UserParametersService: Couldn't retrieve the user");
        else {
          //Accessing subId and creating a promise 
          cognitoUser.getUserAttributes(
            function getSubId(err, result) {
              let promise = new Promise((resolve, reject) => {
                setTimeout(() => {
                  if (err) {
                    reject('error');
                  } else {
                    let response: any = result[0].getValue();
                    resolve(response);
                  }
                }, 1000);
              });
              //Using the resolved subId to query dynamodb
              promise.then((val) => {
                let clientParams: any = {
                  params: { TableName: environment.ddbTableName }
                };
                if (environment.dynamodb_endpoint) {
                  clientParams.endpoint = environment.dynamodb_endpoint;
                }
                var DDB = new DynamoDB(clientParams);
                var getParams = {
                  TableName: environment.ddbTableName,
                  Key: {
                    'userId': { S: val.toString() },
                  }
                };
                //Executing the query
                DDB.getItem(getParams,
                  function (err, result) {
                    if (err) {
                      console.log(err)
                      reject(err);//handling error with reject
                    } else {
                      console.log("DynamoDBService got user object: " + JSON.stringify(result));
                      response = result;
                      resolve(response); 
                    }
                  }
                );
              }); //error handler should be included here for rejected inner promise
            });
        }
      });
      console.log("Async Work Complete");
      //removed resolve from this section
    }, 1000);
  });
  return promise;
}

Please consider reviewing your variable names for clarity, though it shouldn't affect the functionality. Moving the resolve statement may help resolve the issue.

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

Error: The Class object cannot be found in Object(...)(...)

I've been encountering a TypeError while trying to implement this angular code. The error seems to be generated around Class({constructor: function() {}}), but I'm not exactly sure why. Any help on this would be greatly appreciated. import "hell ...

When running `aws-cdk yarn synth -o /tmp/artifacts`, an error is thrown stating "ENOENT: no such file or directory, open '/tmp/artifacts/manifest.json'"

Starting a new aws-cdk project with the structure outlined below src └── cdk ├── config ├── index.ts ├── pipeline.ts └── stacks node_modules cdk.json package.json The package.json file looks like this: " ...

When the async keyword is added, the return type in Typescript can vary

This situation is really puzzling to me. I wrote a function to calculate the number of documents in a collection getDocCount(): Promise<number> { return MyModel.countDocuments({}); } Everything seemed fine. However, when I removed async since I ...

How to Transfer Deleted List Items from one Unordered List to another in Angular 9 using Event Binding

Greetings to all =) I've recently delved into Angular 9 and I'm really enjoying the component-based approach. To sharpen my skills in property and event binding, I embarked on a project involving building a deck with two lists. English isn't ...

Issue with Material UI grid not rendering properly in TypeScript environment

I've been trying to replicate a grid from material-ui using React and Typescript. You can see a live demo here. I modified the example to work with Typescript, so my demo.tsx file looks like this: Code goes here... If you check out the live demo, y ...

Find out whether the page was reloaded or accessed directly through a hyperlink

I need to find out if the page was accessed directly via a link. If it was, I need to perform a certain action. However, my current implementation is not working as intended, as even a page refresh triggers this action. Is there an alternative method to ch ...

Error suddenly appeared when trying to serve a previously functional project locally: Firebase function module not found

After not making any changes to my firebase-related files, I suddenly started encountering the following issue that I just can't seem to figure out: We were unable to load your functions code. (see above) - It appears your code is written in Types ...

What is the most effective method for designing a scalable menu?

What is the most effective way to create a menu similar to the examples in the attached photos? I attempted to achieve this using the following code: const [firstParentActive, setFirstParentActive] = useState(false) // my approach was to use useState for ...

When the Mat tab is clicked, the Expand Collapse feature associated with it will be displayed

Currently, I am implementing Mat tabs (vertical) in one component and Mat expand/collapse functionality in another component. Upon clicking on a tab, the corresponding Mat expand should be displayed. You can view the progress of my work on this Stackblitz ...

Exploring the (*ngFor) Directive to Iterate Through an [object Object]

Attempting to iterate through the array using *ngFor as shown below. let geographicalArea = [{ "_id": "5e77f43e48348935b4571fa7", "name": "Latin America", "employee": { "_id": "5e77c50c4476e734d8b30dc6", "name": "Thomas", ...

Creating a CSS class in a separate file for an element in Angular 4

Looking for some help with my code setup. Here's what I have: <div class="over"> Content </div> In my component file, this is what it looks like: @Component({ selector: 'app', templateUrl: './app.componen ...

"Encountered a problem with Next JS API while trying to fetch data from the app directory

import { NextResponse } from "next/server"; export async function POST(request: Request) { const data = await request.json(); console.log(data); return NextResponse.json({ foo: "boo" }); } next version = "next": &quo ...

Angular project models

I'm exploring the Core/Shared/Feature design pattern for building large, scalable applications in Angular, and I find myself unsure about where models fit in. Is there a consensus on which module they belong in? I came across a post suggesting that ...

Encountering a tslint issue: "Parsing error: Expression expected"

Could someone provide some insight on this issue? I’m encountering an error message that says Failed to compile. Parsing error: Expression expected with this specific line of code - isLogViewVisible: dashboard?.logView !== null where the variable isLog ...

Guide on creating a detailed list of categories mapped to specific classes that all adhere to a common generic standard

Most TypeScript factory patterns I've encountered rely on a named mapping between a name and the Class type. A basic implementation example: const myMap = { classOne: ExampleClass, classTwo: AnotherClass } (k: string) => { return new myMap[k] } ...

Is there a way to retrieve a compilation of custom directives that have been implemented on the Vue 3 component?

Is there a way to retrieve the list of custom directives applied to a component? When using the getCurrentInstance method, the directives property is null for the current component. I was expecting to see 'highlight' listed. How can I access the ...

What steps can I take to generate a JSON array with this unique format?

The data I received from my angular form is in the array format: [{"name":"Rose","number":"+919224512555"},{"name":"smith","number":"+91975555224"}]. The data represents a dynamic table with columns for name and number. I need to convert the array above i ...

Introduce a fresh parameter into the promise all chain

I am using the code below and it is functioning as expected. However, I now need to incorporate the modifyOpt() function. Currently, the code works and returns args[2] but I also need to include another step... I want to pass the return value (port) from ...

Custom input in Angular 2 rc.5: Form control is missing a value accessor for an unspecified name

My custom input component is designed as follows: import {Component, Provider, forwardRef} from "@angular/core"; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms"; const noop = () => {}; const CUSTOM_INPUT_CONT ...

Injecting singletons in a circular manner with Inversify

Is it possible to use two singletons and enable them to call each other in the following manner? import 'reflect-metadata'; import { Container, inject, injectable } from 'inversify'; let container = new Container(); @injectable() cla ...