【问题标题】:Node js not resolving array of promisesNode js没有解析承诺数组
【发布时间】:2014-10-08 11:04:06
【问题描述】:

我正在尝试执行多个异步请求并尝试使用 Promise 获取输出。

如果我有多个请求排队,Q.all(promises).then () 函数似乎不起作用。对于单个请求,所有承诺都已解决。示例代码在这里。

var request = require('request');
var Q = require('q');

var sites = ['http://www.google.com', 'http://www.example.com', 'http://www.yahoo.com'];
// var sites = ['http://www.google.com']

var promises = [];

for (site in sites) {
  var deferred = Q.defer();
  promises.push(deferred.promise);
  options = {url: sites[site]};

  request(options, function (error, msg, body) {
    if (error) {
      deferred.reject();
    }

    deferred.resolve();
  });
}

Q.all(promises).then (function () {
  console.log('All Done');
});

我在这里做错了什么?

苏利亚

【问题讨论】:

  • 您需要提供更多详细信息 - 运行上述代码时究竟会发生什么?
  • "我在这里做错了什么?" - 使用(隐式)全局 siteoptions 变量。使用for in enumeration on arrays。此外,它失败的原因:您的 deferred 将被后续调用覆盖,您的回调不是对它的闭包 - 它总是尝试解决单个最后一个 deferred

标签: javascript node.js promise q


【解决方案1】:

这是我在场景中要做的,这是整个代码:

var Q = require('q');
var request = Q.nfbind(require('request'));

var sites = ['http://www.google.com', 'http://www.example.com', 'http://www.yahoo.com'];
var requests = sites.map(request); 

Q.all(requests).then(function(results){
   console.log("All done") // you can access the results of the requests here
});

现在说明原因:

  • 始终在尽可能低的级别上承诺,承诺请求本身而不是特定请求。更喜欢自动承诺而不是手动承诺,以免犯愚蠢的错误。
  • 处理集合时 - 使用 .map 比手动迭代它们更容易,因为我们在这里为每个 URL 生成一个操作。

此解决方案也很短,并且需要最少的嵌套。

【讨论】:

  • 我意识到我的错误是与闭包合一。但我会接受这个答案,因为我发现了另一种处理承诺的方式。谢谢
  • @Salman 请详细说明 - 并随时提出另一个问题。我在发布之前测试了代码并且它有效。
  • 我不知道为什么我运行的 cldnt 可能是我这边的事情,所以我已经删除了我的评论。
【解决方案2】:

问题是您在 for 循环的每个刻度上都更改了 deferred 的值。因此,在您的示例中实际解决的唯一承诺是最后一个。

要修复它,您应该在某些上下文中存储deferred 的值。最简单的方法是使用Array.prototype.forEach() method 而不是for 循环:

sites.forEach(function (site){
  var deferred = Q.defer();
  var options = {url: sites[site]};
  promises.push(deferred.promise);

  request(options, function (error, msg, body) {
    if (error) {
      deferred.reject();
    }

    deferred.resolve();
  });
})

您还错过了 var 声明 options 变量。在 JavaScript 中,它意味着声明一个全局变量(或 node.js 中的模块范围变量)。

【讨论】:

  • 其实使用map是一个更简单的方法,所以你不必手动做promises.push()
  • 啊.. 关闭。为什么我之前没有想到。
【解决方案3】:

不要使用for..in 来遍历数组。这实际上所做的是将site 设置为0, 1, 2,但这并不能很好地工作。使用其他形式的迭代,例如常规的 for 循环或 Array.prototype.forEach

sites.forEach(function (site) {                                                 
  var deferred = Q.defer();                                                     
  promises.push(deferred.promise);                                               
  options = {url: site};       

【讨论】:

    猜你喜欢
    • 2017-07-09
    • 1970-01-01
    • 2016-09-26
    • 2023-01-16
    • 2016-12-03
    • 2018-04-13
    • 2023-04-06
    • 1970-01-01
    • 2020-07-08
    相关资源
    最近更新 更多