节点承诺循环等待结果

node promise for loop wait for result

本文关键字:结果 等待 循环 承诺 节点      更新时间:2023-09-26

如何等待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);
    });
});

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

  1. 使用return等待promise的完成。在承诺链中,没有任何东西实际解决承诺值,除非它是return ed。(您也应该将此用于message.find(),因为它也给您一个承诺。)
  2. 将数组构造为承诺数组,而不是迭代并在承诺解析时将其推入数组。
  3. 使用Promise.all()收集承诺对象- all()只有在所有传递给它的承诺都被解决后才返回。
  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);
});

所以我认为这是一个好主意,尝试解决它与生成器和承诺的组合,我不确定这是最好的方式去,但这是一个很好的实践,两者的组合,所以我给了它一个尝试。

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

这里是一个更简单的例子,我第一次尝试在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) }
                       );
        }
    });
});