首页 > 解决方案 > 在 ForEach 循环 Firebase Firestore 之后使用 Promises 数组

问题描述

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

我相当确定最好的方法是使用 Promises.all 来返回我给定的数组。但是,在尝试实现这一点时,我遇到了各种问题,并且很难弄清楚如何实现这一点。文档中似乎没有关于如何解决这个问题的好的文档,所以我正在浏览我在这个网站上找到的代码片段,以帮助我理解如何解决这个问题。

多个 Firestore 查询,单个承诺/回调

在从我的承诺/功能返回之前等待 forEach 完成

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

这是我在使用 Promise 时的尝试。它没有报错,但是当数组的长度大于 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,但这似乎又不起作用。那可能是因为我对异步函数的了解不正确。

标签: typescriptfirebasepromisegoogle-cloud-firestoregoogle-cloud-functions

解决方案


对于 Promise,保持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
});

推荐阅读