【问题标题】:Async function in Firebase resolves the promise even before the function body has finished executingFirebase 中的异步函数甚至在函数体完成执行之前就解决了 Promise
【发布时间】:2020-12-08 10:04:28
【问题描述】:

所以我有一个异步函数,它接受一组自定义对象作为参数,然后遍历每个对象并从 firestore 获取一些数据。 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 的 Promise 值之后被执行。

有人可以帮助我如何让函数在返回 whatsNewObjects.length 之前等待主体执行?

【问题讨论】:

    标签: typescript firebase async-await google-cloud-functions


    【解决方案1】:

    您不应该使用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】:

      问题与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
      

      【讨论】:

      • 感谢 MohamadrezaRahimianGolkhandani,我使用了 : for (const person of theInterestedPeople) { } 语法,这解决了问题
      • 很高兴听到这个消息:)
      猜你喜欢
      • 1970-01-01
      • 2019-02-22
      • 2018-03-03
      • 2018-12-29
      • 2021-03-24
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多