node.js - 等待函数永远不会执行

标签 node.js typescript firebase google-cloud-firestore google-cloud-functions

我有一个函数,它迭代一个字符串数组,其中每个字符串代表一个用户的 UID。该函数应该访问每个用户的个人资料,检查他们当前的信誉(与 SO 相同),然后将 uid 和信誉的映射推送到新数组。

第二个数组总是空的,所以我放置了一些日志来检查发生了什么。这是我的功能:

candidates.forEach(async id => {
  console.log('user log ' + id);

  const snap2 = await db.doc('communities_data/' + community.id + '/profiles/' + id).get();
  const user = snap2.data();
  console.log('user ' + user);

  if (user !== undefined) {
    console.log(user + ' just user');
    const reputation = (user.reputation as number);
    candidatesWithReputation.push(new UserAndReputation(id, reputation));
  } else {
    console.log('user undefined ');
  };
});

第一个总是打印 'user log ' +id 并按应有的方式打印用户的 id,所以我知道第一个数组就可以了。 但没有其他日志打印。曾经。我的第一个想法是我可能走错路了?但我已经检查了一百万次,这是用户个人资料在我的数据库中的路径。

例如,这可能是配置文件的路径: communities_data/hfd98HDKKhfEwe6W/profiles/bqSFS04LKJDbfhdwU

知道哪里失败了

最佳答案

我的猜测是您遇到了时间问题。 .forEach() 在继续下一次迭代之前不会等待异步操作完成(它不会查看代码从异步回调返回的 promise ),因此在 .forEach() 之后,您的第二个数组在 .forEach() 循环之后将始终为空,因为它尚未填充(循环中的异步调用尚未完成)。

所以基本上,您很少想在 .forEach() 回调中使用 async/await,因为循环不尊重它,并且您无法知道循环外的一切何时完成。

虽然您没有显示此代码的更大上下文,但这里通常的解决方案是使用常规的 for 循环或 for/of 循环,它将等待 await 语句,因此您可以更轻松地知道一切何时完成。

这是一种方法:

async function someFunction() {

    // other code here


    for (let id of candidates) {
      try {
          console.log('user log ' + id);

          const snap2 = await db.doc('communities_data/' + community.id + '/profiles/' + id).get();
          const user = snap2.data();
          console.log('user ' + user);

          if (user !== undefined) {
            console.log(user + ' just user');
            const reputation = (user.reputation as number);
            candidatesWithReputation.push(new UserAndReputation(id, reputation));
          } else {
            console.log('user undefined ');
          };
      } catch(e) {
          console.log(e);
          // decide what to do upon error, 
          //     skip it and proceed?
          //     stop further processing?
      }
    }
    // candidatesWithReputation should now be valid here
    console.log(candidatesWithReputation);

   // other code here
}

请注意,包含函数必须声明为 async 才能允许您在 for 循环内使用 await

<小时/>

为了获得更好的性能,您还可以并行执行所有这些查找,并使用 Promise.all() 查看它们何时完成:

function someFunction() {

    // other code here

    Promise.all(candidates.map(id => {
        return db.doc('communities_data/' + community.id + '/profiles/' + id).get().then(snap2 => {
            return snap2.data();
        }).catch(err => {
            // decide what to do about an error here
            // this implementation skips any queries with error and proceeds with the others
            return undefined;
        });
    })).then(users => {
        let candidatesWithReputation = [];
        for (user of users) {
            if (user !== undefined) {
                // I've not seen this "user.reputation as number" syntax??  Typescript?
                const reputation = (user.reputation as number);
                candidatesWithReputation.push(new UserAndReputation(id, reputation));
            }
        }
        return candidatesWithReputation;
    }).then(users => {
        // list of users with reputation here
        console.log(users);
        // further processing here
    }).catch(err => {
        console.log(err);
    });
}

关于node.js - 等待函数永远不会执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57403552/

相关文章:

jquery - Meteor Galaxy 部署 - 托管时出现控制台错误且不显示路由

typescript - 如何在Typescript中指定数字的最小-最大范围?

typescript - 在 Typescript 中索引其他属性的属性

swift - 'UIPastebaord.general.hasStrings' 不适用于 iOS 14.0

javascript - 如何在 firestore 中离线读取文档并写入(在线和离线)?

android - 如何防止在另一个 Activity 中调用一个 Activity 的 addValueEventListener?

node.js - 如何在 Express.js 中从 Axios 接收 Blob 对象

node.js - express + Mongoose : async/await returning undefined

node.js - 将 OAuth 与 Kuzzle 集成

intellij-idea - IntelliJ IDEA 在 rxjs5 中找不到 Observable 的运算符