【问题标题】:node promise for loop wait for result节点承诺循环等待结果
【发布时间】:2016-09-12 12:30:40
【问题描述】:

如何等待 for 循环进入下一个循环?

如何确保 userdetails 已执行,并且 realresult.playername 在传递之前已分配给新变量?

代码:

return new Promise( function (resolve, reject) {

    arr = [];


    messages.find({convid: convid}).then(function(result) {

        for(var a in result) {
            realresult = result[a];

            userData.userDetails(realresult.userid).then(function (result) {
                realresult.playername = result.username;
            });
            userData.usercashinfo(realresult.userid).then(function (resulttwo) {
                realresult.playerdetails = resulttwo;
            });

            arr.push(realresult);

        }

        return resolve(arr);
    });
});

【问题讨论】:

标签: javascript node.js asynchronous promise


【解决方案1】:

您正在尝试编写一个 Promise,当它解析时,返回已解析的 Promise 值数组。您应该在这里做两件事:

  1. 使用return 等待承诺的完成。在 Promise 链中,除非是 returned,否则不会真正解决 Promise 值。 (你也应该将它用于message.find(),因为它也给了你一个承诺。)
  2. 将数组构造为 promise 数组,而不是迭代并在 promise 解析时将它们推送到数组中。
  3. 使用Promise.all() 收集promise 对象-all() 仅在传递给它的所有promise 都解决后才返回。
  4. (可选)不要重复使用result 变量名来表示多个含义。这里没有错,但会造成不必要的混乱。

综合起来,这看起来像:

return messages.find(...).then(function(result) {
  var promiseArr = [];
  for (var a in result) {
    promiseArr.push(
      promise.all([userData.userDetails(...), userData.usercashinfo(...)])
      .then(function(detailinfo) {
        var realresult = result[a];
        var details = detailinfo[0];
        var cashinfo = detailinfo[1];
        realresult.playername = details.username;
        realresult.playerdetails = cashinfo;
        return realresult;
    });
  }
  return Promise.all(promiseArr);
});

【讨论】:

  • 嘿@yoz,我更新了我的帖子,你能做一些编辑来让它工作吗?
【解决方案2】:

所以我认为尝试使用生成器和 Promise 的组合来解决它是一个好主意,我不确定这是最好的方法,但它是两者结合的好习惯,所以我给了它试一试。

这个想法是生成器函数在开始新的迭代之前等待回调函数,而回调函数在告诉生成器函数继续迭代之前等待两个承诺完成。

here is a more simple example that I first tried on codepen

return new Promise( function (resolve, reject) {
    arr = [];
    messages.find({convid: convid}).then(function(result) {
        function* iterations() {
            for (var i = 0; i < result.length; i++) {
                realresult = result[i];
                try {
                    var cbResult = yield cb(result[i].userid);
                    realresult.playername = cbResult.playername;
                    realresult.playerdetails = cbResult.playerdetails;
                    arr.push(realresult);
                } catch (e) { reject(e) }
            }
            return arr.value;
        }

        var it = iterations();
        it.next();

        function cb(userid) {
            Promise.all([
                       userData.userDetails(userid),
                       userData.usercashinfo(userid)
                       ]).then(
                           function(values) {
                               var realresult = {playername : values[0], playerdetails : values[1]}
                               returnValue = it.next(realresult);
                               if (returnValue.done) {
                                   resolve(returnValue);
                               }
                           },
                           function(e) { reject(e) }
                       );
        }
    });
});

【讨论】:

  • 这段代码非常复杂,不处理任何错误。而不是使用生成器,你应该去async/await
  • prntscr.com/ch6i49 我做了你所做的@naortor,但是它不会以简单的响应返回数组?作为 [0] 和 [1] ?
  • @Bergi ,在这种情况下最好的是什么?
  • @maria 我编辑了答案,因此它将根据需要返回数组。但它更像是一个 POC——正如 Bergi 所说,它还没有处理错误——你应该将 yield 调用包装在 try / catch 块中,并从 promise 中拒绝错误
猜你喜欢
  • 2017-11-01
  • 2019-12-10
  • 2021-10-03
  • 2019-06-30
  • 2017-12-16
  • 2022-12-08
  • 2015-12-22
  • 2020-08-16
  • 2016-04-13
相关资源
最近更新 更多