【问题标题】:How to loop through an array of Firebase Firestore documents and push values into array如何遍历一组 Firebase Firestore 文档并将值推送到数组中
【发布时间】:2022-01-10 01:36:04
【问题描述】:

我正在 node.JS 中编写一个 Firebase 云函数,它从 Firebase Firestore 读取用户数据。 我无法将令牌值推入令牌数组并在函数末尾返回所有令牌。我的代码如下:

function getTokens(subscribers) {
    return new Promise(async function (resolve, reject) {
        const tokenArray = [];
        subscribers.forEach(async (subscriber) => {
            await firestore
                .collection('users')
                .doc(subscriber)
                .get()
                .then((user) => {
                    console.log("Getting user data for user: ", user);
                    const tokens = user.data().tokens;
                    if (tokens) {
                        tokens.forEach((token) => {
                            console.log("Adding token to token array"); // data is available here but does not push into tokenArray
                            tokenArray.push(token);
                        });
                    }
                }).catch((error) => { console.error(error); reject(error); });
        });
        console.log("Token Array -- Final: ", tokenArray);
        resolve(tokenArray);
    });
};

【问题讨论】:

    标签: javascript node.js firebase google-cloud-firestore google-cloud-functions


    【解决方案1】:

    OP代码可以更正,更简洁如下:

    async function getTokens(subscribers) {
      const getUser = subscriber => firestore.collection('users').doc(subscriber).get();
      const promises = subscribers.map(getUser);
      const users = await Promise.all(promises);
      return users.map(user => user.data().tokens).flat()
    }
    

    一些注意事项:

    • 将函数装饰为async,因为它包含一个等待
    • 不要使用 Promise.new() 创建任何额外的承诺,Firestore 的 get() 会返回一个承诺
    • 使用map 在数组中收集get 承诺,并使用Promise.all() 运行它们
    • 映射结果用户的data.tokens 会生成一个数组数组。把它压平,你就完成了。
    • catch 只会扔,就像没有接球一样

    【讨论】:

    • 我喜欢 .map() 和 .flat()。不错!
    【解决方案2】:

    您不能在forEach 循环中使用async-await。尝试映射一组承诺,然后使用Promise.all(),如下所示:

    function getTokens(subscribers) {
      return new Promise(async function (resolve, reject) {
        
        const subscribersDocs = await Promise.all(
          subscribers.map((subscriber) => {
            return firestore.collection("users").doc(subscriber).get();
          })
        );
    
    
        const tokenArray = subscribersDocs.reduce((acc, curr) => {
          const tokens = curr.data().tokens;
          if (tokens) {
            acc = acc.concat(tokens);
          }
          return acc;
        }, []);
    
        console.log("Token Array -- Final: ", tokenArray);
        resolve(tokenArray);
      });
    }
    

    也结帐:Using async/await with a forEach loop

    【讨论】:

    • 几个性能点:如果您在开始时的subscribers 不是一个完全任意的列表,最好使用查询来选择它们。 reads 的费用相同,但只有一次往返。同样,您应该能够使用.concat(),而不是循环遍历tokens 并使用push()
    • 感谢@LeadDreamer。我应该提到 in 运算符,尽管它仅在数组最多包含 10 个元素时才有用。
    猜你喜欢
    • 2021-03-27
    • 1970-01-01
    • 2018-09-29
    • 2018-12-09
    • 1970-01-01
    • 2021-02-03
    • 2021-10-04
    • 1970-01-01
    • 2020-01-19
    相关资源
    最近更新 更多