如何遍历一组 Firebase Firestore 文档并将值推送到数组中

Posted

技术标签:

【中文标题】如何遍历一组 Firebase Firestore 文档并将值推送到数组中【英文标题】:How to loop through an array of Firebase Firestore documents and push values into array 【发布时间】: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);
    );
;

【问题讨论】:

【参考方案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 个元素时才有用。

以上是关于如何遍历一组 Firebase Firestore 文档并将值推送到数组中的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI Firebase Firestore 查询函数

如何在 Firebase Firestore 完成之前暂停 Javascript MAP? Promise、Async/Await 或两者兼有

尝试将一组对象保存到 Firestore 并将其加载回来

Firebase Firestore 读取和定价

Tableview 中的 Swift Firebase Firestore 数据

如何从 Firebase 获取一组对象?