【问题标题】:Promises inside loop to wait承诺在循环内等待
【发布时间】:2017-12-16 09:33:57
【问题描述】:

我有这个代码:

var services = ['EC2', 'S3', 'RDS', 'IAM']
var promises = [];

for(var i = 0; i < services.length; i++) {
   var promise = awsStatus('us-east-1', services[i])
      promises.push(promise);
      console.log(promises);
}

q.all(promises).then(function(data){
   console.log(promises);
});

它应该使用awsStatus 方法在services 数组上循环。问题是有时我得到了我想要的所有结果:

{ service: 'IAM', status: 0 }
{ service: 'EC2', status: 0 }
{ service: 'RDS', status: 0 }

但有时我会得到不完整的结果。我以为在awsStatus 之后我需要.then 但这也没有解决这个问题。这段代码还有什么问题?

既然有评论,我也试过这个:

var services = ['EC2', 'S3', 'RDS', 'IAM']
var promises = [];

for(var i = 0; i < services.length; i++) {
   var promise = awsStatus('us-east-1', services[i]).then(function(promise){
      promises.push(promise);
      //console.log(promises);
});
}
q.all(promises).then(function(data){
   console.log(promises);
});

它会产生相同的结果。

【问题讨论】:

  • awsStatus('us-east-1', item).then(function(promise) { promises.push(promise); }) 并确保 awsStatus 这应该返回承诺
  • 我也尝试过,但仍然得到相同的结果。
  • 然后试试这个异步库 (github.com/caolan/async)。它提供了非常直观的方式来处理这样的异步情况
  • 我不会再添加另一个外部库 - 这是一个应该很容易解决的简单案例。但是,我不完全确定您要做什么 - 记录 Promise 数组只会显示 Promise 对象,而不是它们的结果。你能澄清一下吗?
  • 我觉得这也很简单。不知道为什么它不起作用。我正在尝试为服务数组中的每个元素运行 awsStatus,等待所有结果并显示它们。

标签: javascript node.js promise q


【解决方案1】:

我可以建议使用async 库的解决方案,如下所示:

var services = ['EC2', 'S3', 'RDS', 'IAM']
async.map(services, 
  function(item, done){
    awsStatus('us-east-1', item).then(
      function(){
        done(null, "Completed item " + item);
      }, 
      function(err){
        done(err + " in item " + item, null);
      }
    );
  }, 
  function(err, results){
    if(err) return console.log(err);
    console.log(results);
  }
);

如果其中一个承诺返回错误,它将失败并停止执行。如果不想停止你可以在promise的错误函数中返回null而不是错误信息作为done方法的第一个参数

【讨论】:

    【解决方案2】:

    尝试使用.each

    Promise.each(services, function(service) {
      return awsStatus('us-east-1', service).then(function(promise){
          promises.push(promise);
          //console.log(promises);
      });
    }).then(function() {
      console.log('Done with all instances');
    });
    

    【讨论】:

    • 我试过了,得到了一些我认为与 aws-status 模块有关的随机错误:TypeError: Cannot read property 'channel' of undefined
    • 是的,这与 awsStatus 有关
    【解决方案3】:

    你的代码有两个问题:

    1. 使用q.all() 并不能保证代码会等待所有的promise 解决。如果其中一个被拒绝,then 方法将被调用,而不是等待其余的承诺。您可以改用q.allResolved() 来解决这个问题。
    2. 您正在记录错误的对象。您应该记录 Promise 的结果,而不是 Promise 对象本身。

    如何解决这两个问题的示例:

    q.allResolved(promises).then(function(results) {
      console.log(results);
    }).catch(function(err) {
      console.error(err);
    });
    

    【讨论】:

    • 我也试过allSettled(),记录结果时得到一个空数组。
    • awsStatus 是你实现的,还是某个库?
    • 我将其更改为使用allResolved,并添加了一个catch。立即尝试 - 如果某些内容被拒绝,它应该会向您显示错误。
    猜你喜欢
    • 2022-12-08
    • 2019-04-26
    • 2016-04-13
    • 2017-11-01
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2020-05-15
    • 2022-01-03
    相关资源
    最近更新 更多