在ForEach循环Firebase Firestore之后使用承诺数组

时间:2019-09-17 22:46:25

标签: typescript firebase promise google-cloud-firestore google-cloud-functions

我想将具有与生成的数字相同的数字的用户推送到我的数组中。循环完成后,我需要获取循环结果,例如数组长度,数组中的项目以及对数组中的用户执行各种操作的项目,例如记入他们的帐户。

我相当确定做到这一点的最佳方法是使用Promises.all返回给定数组的诺言。但是,在尝试实现此功能时,我遇到了各种各样的问题,并且很难将精力集中在如何实现此功能上。在文档中似乎没有关于如何解决该问题的好的文档,因此,我将浏览本网站上的代码片段,以帮助我了解如何解决此问题。

Multiple Firestore queries, single promise / callback

Waiting for a forEach to finish before return from my promise / function

一直是我的两个主要参考。

这是我使用诺言时的尝试。并没有出错,但是当数组的长度大于1时,似乎并没有意识到数组的长度大于1。

export const prize1 = functions.pubsub.schedule('every 2 minutes').onRun((context: any) => {

    function getUsers() {
        let ranNum2 = '';
        for (let _i = 0; _i < 2; _i++)
            ranNum2 += String(Math.floor(Math.random() * 9) + 0);

        let winnersP2: string[] = [];

        const usersRef = db.collection('users');
        let dbPromises: string[] = [];

        let _allUsers = usersRef.get().then((userSnapshot: any) => {
                userSnapshot.forEach((userDoc: any) => {
                    userDoc.ref.collection('numbers').get().then((numSnapshot: any) => {
                        numSnapshot.forEach((numDoc: any) => {


                            let pp = Number(numDoc.data().numbers);

                            if (pp == Number(ranNum2))
                                winnersP2.push(userDoc.ref.id);

                        });

                        return Promise.all(dbPromises).then(results => {
                            if (dbPromises.length > 0)
                                console.log("GREATER THAN 0");
                                //do my stuff
                            if (results.length > 0)
                                console.log("GREATER THAN 0");
                                //do my stuff

                        })

                    });
                });
            })
            .catch((error: any) => {
                console.log("Error getting document: ", error);
            });

    }

    return null;

});

这是我要修改的基本代码。

export const prize1 = functions.pubsub.schedule('every 2 minutes').onRun((context: any) => {
        let ranNum2 = '';

        for (let _i = 0; _i < 2; _i++)
            ranNum2 += String(Math.floor(Math.random() * 9) + 0);

        let winnersP2: string[] = [];

        const usersRef = db.collection('users');
        let _allUsers = usersRef.get().then((userSnapshot: any) => {
            userSnapshot.forEach((userDoc: any) => {
                userDoc.ref.collection('numbers').get().then((numSnapshot: any) => {
                    numSnapshot.forEach((numDoc: any) => {

                        let pp = Number(numDoc.data().numbers);

                        if (pp == Number(ranNum2))
                            winnersP2.push(userDoc.ref.id);

                    });
                    if (winnersP2.length > 0)
                    //do my stuff
                });
            });

        });

    })
    .catch((error: any) => {
        console.log("Error getting document: ", error);
    });

return null;
});

我也尝试过使用setTimeOut等到for循环完成之后,再看该数组是否大于0,但这似乎还是没有用。那可能是因为我对异步函数的了解不正确。

1 个答案:

答案 0 :(得分:0)

有了承诺,保持thencatch块对齐很重要。创建嵌套块会引起混乱。您还需要确保从每个块返回一个结果,该结果将在下一个块中处理。

您正试图从每个用户记录的numbers文档中读取内容,并处理所得的数字列表。看起来类似于以下内容:

userCollection.get().then((docs) => {
  return Promise.all(docs.map((docRef) => {
    return docRef.collection('numbers').get();
  });
}).then((numbersDocs) => {
  // do something with the list of docs
});