In Firebase, the async function completes the promise even as the function body is still executing

I'm currently facing an issue with an async function I've written. It takes an array of custom objects as an argument, loops through each object, retrieves data from Firestore, converts it into another custom object, and adds it to an array. The function then returns the length of this array.

async function getCompsReceived(theInterestedPeople: InterestedPerson[]) {

  const whatsNewObjects: WhatsNewObject[] = []

  theInterestedPeople.forEach(async (person) => {

    const documentsSnapshot = await 
    db.collection('Users').doc(person.uid).collection('complimentsReceived')
      .orderBy('receivedTime', 'desc')
      .limit(documentLimit)
      .get()

  if (documentsSnapshot.empty) {
    console.log(`${person.userName} has no compsReceived`)
    return
  }


  await documentsSnapshot.forEach((newCompReceived: { receiverUid: string; receiverUserName: string; 
    complimentsReceivedContent: string | null; hasImage: boolean | null; senderUid: string | null; 
      senderUserName: string | null; noOfLikes: number | null; receivedTime: number | null; 
        complimentId: string | null} ) => {
         //Add each new Compliment to the WhatsNewObjects Array
         const whatsNewDoc = new WhatsNewObject(
           newCompReceived.receiverUid,
           newCompReceived.receiverUserName,
           true,
           newCompReceived.complimentsReceivedContent,
           newCompReceived.hasImage,
           newCompReceived.senderUid,
           newCompReceived.senderUserName,
           newCompReceived.noOfLikes,
           newCompReceived.receivedTime,
           newCompReceived.complimentId,
           'PERSON_COMPLIMENT_RECEIVED'
         )

    whatsNewObjects.push(whatsNewDoc)

  })

  console.log(`length of whatsNewObjects after adding ${person.userName}'s compsReceived is      
    ${whatsNewObjects.length}`)

})

console.log(`returning the length of WhatsNewObjects at getCompsReceived which is ${whatsNewObjects.length}}`)
    return whatsNewObjects.length

}

However, I've noticed that this function always returns a value of 0. Looking at the console logs in Firebase, it seems that the body of the function is executed after the function has already returned the Promise of type number.

Could someone please assist me in figuring out how to make the function wait for the body to be executed before returning the length of whatsNewObjects?

Answer №1

Avoid using forEach to iterate over async code because it does not support await. Instead, consider using for..of for handling asynchronous operations:

async function getCompsReceived(theInterestedPeople: InterestedPerson[]) {

    const whatsNewObjects: WhatsNewObject[] = []

    for (const person of theInterestedPeople) {
        const documentsSnapshot = await db.collection('Users').doc(person.uid).collection('complimentsReceived')
            .orderBy('receivedTime', 'desc')
            .limit(documentLimit)
            .get();

        if (documentsSnapshot.empty) {
            console.log(`${person.userName} has no compsReceived`)
            return;
        }

        documentsSnapshot.forEach((newCompReceived: {
            receiverUid: string; receiverUserName: string;
            complimentsReceivedContent: string | null; hasImage: boolean | null; senderUid: string | null;
            senderUserName: string | null; noOfLikes: number | null; receivedTime: number | null;
            complimentId: string | null
        }) => {
            //Add each new Compliment to the WhatsNewObjects Array
            const whatsNewDoc = new WhatsNewObject(
                newCompReceived.receiverUid,
                newCompReceived.receiverUserName,
                true,
                newCompReceived.complimentsReceivedContent,
                newCompReceived.hasImage,
                newCompReceived.senderUid,
                newCompReceived.senderUserName,
                newCompReceived.noOfLikes,
                newCompReceived.receivedTime,
                newCompReceived.complimentId,
                'PERSON_COMPLIMENT_RECEIVED'
            );
            whatsNewObjects.push(whatsNewDoc);

        })
        console.log(`length of whatsNewObjects after adding ${person.userName}'s compsReceived is ${whatsNewObjects.length}`);
    }
    console.log(`returning the length of WhatsNewObjects at getCompsReceived which is ${whatsNewObjects.length}}`);
    return whatsNewObjects.length;
}

Answer №2

The issue revolves around the usage of the forEach method, which runs asynchronously even when async/await is employed in the callback function. To resolve this, simply replace forEach with any form of for loop.

for (let index = 0; index < theInterestedPeople.length; index++) {
    const person = array[index];
    ....your code
}
// or
for (const person of theInterestedPeople) {
    
}
// or

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

Encountering a Login Issue with Firebase Google Authentication in Angular 16

I am currently working on implementing a Google sign-in/login feature in Angular 16 using Firebase. However, when I try to click the "LogIn" button, I encounter the following error: "ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of ...

Implementing Formik in React for automatic updates to a Material-UI TextField when blurred

Presently, I am developing a dynamic table where users can simultaneously modify multiple user details in bulk (Refer to the Image). The implementation involves utilizing Material-UI's <TextField/> component along with Formik for managing form s ...

What is the best way to convert a promise using an async await function into an observable?

Currently, I have set up a Nestjs rest server that includes a controller and a service. Within the controller, there is a get function that is triggered when a get request is made: @Get() getAllFoos() { return this.fooService.getAllFoos(); } Inside ...

Generating output from a callback function in TypeScript

When I execute a graphql query, the showUsers function is supposed to display all users (styled as boxes). However, at the moment, nothing is showing up. I am utilizing a functional component instead of a class component. This function is invoked after m ...

The Semantic UI Tabs in Angular 4 only function properly once they have been clicked on

I have set up semantic UI tabs in my app.component.html as shown below: <div class = "ui container"> <h1>Header/h1> <hr> <div style = "background-color: rgb(194, 221, 240);" class="ui top attached tab ...

Utilizing HTML imports in Typescript for efficient use as TemplateStringLiteral

Recently, I started using TypeScript for the first time and I'm looking to integrate it into my webpack build. Currently, I am working with ts-loader and babel-loader to load TypeScript files while also attempting to include HTML files within the scr ...

Navigating Through Angular Components

I have a layout with 3 components arranged like this: <app-header></app-header> <app-body></app-body> <app-footer></app-footer> However, I want to change the positioning of the footer and body as shown below: <app-he ...

Import statements cannot be used outside of a module when working with a private npm package in cucumber.js

Utilizing cucumberjs to test various components of my project has been successful. However, I encountered an issue in one step where I utilize a zod schema that is defined within a private npm module: // within the private npm package: // constant.js impor ...

What is the best way to retrieve data from Firebase and then navigate to a different page?

I am facing an issue with my app where I have a function that retrieves data from Firebase. However, after the completion of this Firebase function, I need to redirect it to another page. The problem is that when I press the button, the redirection happe ...

The presence of a setupProxy file in a Create React App (CRA) project causes issues with the starting of react-scripts,

I have implemented the setupProxy file as outlined in the documentation: const proxy = require('http-proxy-middleware'); module.exports = function (app) { app.use( '/address', proxy({ target: 'http ...

Having trouble looping through an array in Angular 2?

I am currently using a FirebaseObjectObservable to retrieve the value of a property from my firebase database. The property can have multiple values, so I stored them in a local array variable. However, I ran into an issue while trying to iterate through ...

Getting the hang of using and translating typescript .tsx files with jsx in React-native

Recently, I have ventured into the world of React-native after having experience with reactjs+typescript. Wanting to test its capabilities, I decided to set up a simple project. My tool of choice for development is VS Code. After following a basic tutoria ...

Establishing a typescript class as an interface

While attempting to upgrade to TypeScript 3.5, I ran into an issue with a signature that has been overlooked by the ts-compiler, despite being present for years. A third-party framework (knockoutJS) requires me to pass something that adheres to this: int ...

Is the callback not being triggered in the Stripe webhook? Or could I be overlooking something important?

I am currently working on a project using Next.js with Strapi and Stripe. The issue I am facing involves a webhook that is supposed to execute the markProductAsSold callback after a successful payment. However, this callback only runs correctly on localhos ...

Typescript: The .ts file does not recognize the definition of XMLHttpRequest

I have encountered an issue with a .ts file containing the following code: var xhttp = new XMLHttpRequest(); After running the grunt task to compile the ts files using typescript, no errors were reported. However, when I attempt to instantiate the class ...

Using the decorator in VueJS Typescript allows you to easily define dynamic computed properties

On my hands is a component structured like this: @Component({ computed: { [this.stateModel]: { get() { return this.$store[this.stateModel]; } } } }) class Component extends Vue{ @Prop({ de ...

Put Jest to the test by testing the appendFileSync function

I am currently working on creating a test for appendfilesync function. When using a logger, I noticed that one line of code is not covered in my tests. Below is the code snippet I am referring to (please note that I am using tslog for logging purposes): ex ...

Ways to increase the number of responses in an Express app after the initial response

In order to comply with the Facebook messenger API requirements, a 200 response must be sent immediately upon receiving the webhook request on my server, within 20 seconds. However, this process may take longer than the execution time of other middleware f ...

The Enigmatic Essence of TypeScript

I recently conducted a test using the TypeScript code below. When I ran console.log(this.userList);, the output remained the same both times. Is there something incorrect in my code? import { Component } from '@angular/core'; @Component({ sel ...

There was an unhandled exception that occurred due to a missing file or directory with the lstat error on 'D:a1s ode_modulesquill'

ngx-quill is causing issues in production, any suggestions? I am currently using "ngx-quill": "^13.4.0", but it is unable to find Quill on my server even though it works locally. The problem persists in the pipeline... An unhandled exception has occurred ...