Итак, у меня есть асинхронная функция, которая принимает в качестве аргумента массив настраиваемых объектов, затем перебирает каждый из этих объектов и получает некоторые данные из хранилища огня. Данные из Firestore преобразуются в другой настраиваемый объект и добавляются к другому в массив настраиваемых объектов. Длина этих объектов возвращается функцией.

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

}

Проблема в том, что эта функция всегда возвращает 0, и с операторами журнала, напечатанными на консоли Firebase, я вижу, что тело функции выполняется после того, как функция уже вернула значение, которое является обещанием типа number.

Может ли кто-нибудь помочь мне в разделе Как заставить функцию ждать выполнения тела, прежде чем возвращать whatsNewObjects.length?

0
Anudeep Ananth 19 Авг 2020 в 10:19

2 ответа

Лучший ответ

Вы не должны использовать forEach для итерации асинхронного кода, поскольку он не await. Он просто выстрелит и забудет. Вместо этого используйте for..of:

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;
}
2
Christian 19 Авг 2020 в 08:01

Проблема связана с тем, что forEach на самом деле выполняется асинхронно, даже если вы используете async/await в функции обратного вызова. Вы можете решить эту проблему, просто заменив forEach на любые итераторы for.

for (let index = 0; index < theInterestedPeople.length; index++) {
    const person = array[index];
    ....your code
}
// or
for (const person of theInterestedPeople) {
    
}
// or
1
MohamadrezaRahimianGolkhandani 19 Авг 2020 в 08:51