【问题标题】:Wating for all finished request in a loop with node request使用节点请求在循环中等待所有完成的请求
【发布时间】:2015-10-06 11:57:09
【问题描述】:

我使用节点请求ajax包。所以,我有一个循环,在每次迭代中它都会向我的服务器发出请求。

// realItems needs the complete value of items assigned
var realItems;

var items = [];
_.forEach(JSON.parse(body), (value, key) => {
  request('myurl/' + id, (error, response, body) => {
    items = JSON.parse(body)
  });
});

我如何捆绑来自request 包的所有请求,以便最后将items 变量的值分配给realItems

// 编辑:

我使用 react js,所以在这种情况下 realItems 是一个状态,我不能在每次循环迭代中触发它,因为渲染会在每个 setState 上触发

【问题讨论】:

  • JSON.parse(body) 的结果是什么?为什么您在request() 通话中没有使用其中的任何内容?

标签: javascript request


【解决方案1】:

有很多方法可以解决这个问题。这是一种不保留结果顺序的蛮力方法:

var items = [];
var cnt = 0;
_.forEach(JSON.parse(body), (value, key) => {
  ++cnt;
  request('myurl/' + value.id, (error, response, body) => {
    items.push(JSON.parse(body));
    // if all requesets are done
    if (--cnt === 0) {
        // process items here as all results are done now
    }
  });
});

这是一个使用 Bluebird 承诺的版本:

var Promise = require('bluebird');
var request = Promise.promisify(require("request"));
Promise.promisifyAll(request);

var promises = [];
_.forEach(JSON.parse(body), (value, key) => {
    promises.push(request('myurl/' + value.id));
});
Promise.all(promises).then(function(results) {
    // all requests are done, data from all requests is in the results array
    // and are in the order that the requests were originally made
});

还有,这里有一个更简单的 Bluebird promises 方法,它使用了 Bluebird 迭代器:

var Promise = require('bluebird');
var request = Promise.promisify(require("request"));
Promise.promisifyAll(request);

Promise.map(JSON.parse(body), function(value) {
    return request('myurl/' + value.id);
}).then(function(results) {
    // all requests are done, data is in the results array
});

【讨论】:

  • 谢谢!与计数器一起使用可能会起作用,但我还想更喜欢更优雅的方式,比如 Promises。对不起我的代码,它真的很简化。所以, JSON.parse(body) 来自外部请求(它实际上只是一个包含 3 个项目的数组,所以我知道我需要制作多少个循环)。 id 也来自 value 并且在我的代码中 value.id
  • @nutzt - 我添加了一个使用承诺的版本。
  • 我变成ReferenceError: requestAsync is not defined
  • @nutzt - 我更正了。 request() 是一个奇怪的模块,所以你必须以不同的方式承诺它——我的错误。有关该承诺问题的详细信息here
【解决方案2】:

您是否需要使用request 包?我使用async,它与parallel 方法相似,它完全符合您的要求-

https://github.com/caolan/async#parallel

示例:

async.parallel([
  function(callback){
    setTimeout(function(){
        callback(null, 'one');
    }, 200);
  },
  function(callback){
    setTimeout(function(){
        callback(null, 'two');
    }, 100);
  }
],
// optional callback
function(err, results){
    // the results array will equal ['one','two'] even though
    // the second function had a shorter timeout.
});

【讨论】:

    猜你喜欢
    • 2018-10-20
    • 2015-04-17
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    相关资源
    最近更新 更多