【问题标题】:Firebase Functions - Unexpected `await` inside a loop - Cannot read property 'reduce' of undefinedFirebase 函数 - 循环内意外的“等待” - 无法读取未定义的属性“减少”
【发布时间】:2020-11-24 18:07:09
【问题描述】:

我正在使用 Firebase 函数来提取用户数据。因为 Firestore 查询的“IN”查询限制为 10,所以我必须在循环中运行异步调用。

我无法在循环中执行异步标注,因此我必须将标注同步推送到数组中,然后调用 await Promise.all() 以在循环外运行标注。

执行此操作时,我收到来自 Firestore 的错误

TypeError: 无法读取未定义的属性“reduce”

我可以看到结果值是一个 Promise。所以我一定是写错了reducePromise.all()...

如果我可以看到值是一个承诺,为什么承诺会以undefined 的形式出现?

const buildChatMatches = async ({id, matches, singles}) => {
  const existing = singles || {};
  if (Array.isArray(matches) && matches.length > 0) {
    let numberOfDozens = matches.length / 10;
    let results = [];
    let i = 0;
    while (i < Math.ceil(numberOfDozens)) {
      let sliceMatches = matches.slice(i * 10, (i + 1) * 10);
      const query = admin
        .firestore()
        .collection(USER_COLLECTION_NAME)
        .where("id", "in", sliceMatches);
      results.push(query.get());
      i++;
    }
    let allResults = await Promise.all(results);
    return allResults.docs.reduce((map, doc) => {
      map[doc.id] = pickUserInfo(doc.data(), existing[doc.id]);
      return map;
    });
  }
  return {};
};

感谢道格的回答:

let allResults = await Promise.all(results);
allResults.forEach(function(querySnapshot) {
  for (let i in querySnapshot.docs) {
    users.push(querySnapshot.docs[i]);
  }
});

【问题讨论】:

  • 旁注:您在调用reduce 时缺少map 的初始值。 (当您想要的只是一个简单的循环时,不使用reduce 的另一个原因。)

标签: javascript firebase google-cloud-firestore async-await for-await


【解决方案1】:

allResults 将是一个 QuerySnapshot 对象数组。它不会有一个名为docs 的属性,因为它只是一个数组。由于它没有名为docs 的属性,因此allResults.docs 将是未定义的,并且不会有名为reduce 的方法。

您必须以某种方式迭代或映射该 QuerySnapshot 对象数组,以便您可以访问每个快照上的文档。

【讨论】:

  • 谢谢,你说得对,我需要一个嵌套循环来遍历返回的查询结果。我将用 sn-p / 解决方案更新问题
猜你喜欢
  • 2018-06-10
  • 1970-01-01
  • 2018-08-04
  • 2019-01-23
  • 2018-10-30
  • 2018-04-01
  • 2020-03-26
  • 2018-09-13
相关资源
最近更新 更多