http.get请求循环closures问题(节点)

我希望能够在命令行中放入一系列URL,并按照提供的顺序获取这些请求的结果。 我已经研究了闭包,以实现这一点,因为callback不会按顺序执行(更有可能是最快的响应)

for (var i = 2; i < process.argv.length; i++) { (function(index) { http.get(process.argv[index], function (response) { response.pipe(bl(function (err, data) { console.log(data.toString()); })); }); })(i); } 

for循环参数。 然后每个迭代调用IIFE匿名函数,然后调用get请求等等。 但是问题依然存在,它被无序执行。 不按用户要求的顺序。

我究竟做错了什么?

如果您只是试图按顺序logging结果,但希望并行运行请求,那么通常的解决scheme是将结果收集到数组中,然后在完成所有请求时输出结果。

 var count = process.argv.length - 2; var results = new Array(count); for (var i = 2; i < process.argv.length; i++) { (function(index) { http.get(process.argv[index], function (response) { response.pipe(bl(function (err, data) { results[index - 2] = data.toString(); --count; if (count === 0) { for (var j = 0; j < results.length; j++) { console.log(results[j]); } } })); }); })(i); } 

这个暴力方法也可以做得稍微聪明些,以便在完成这个之前的所有请求而不是等待所有的完成时,稍微输出一些结果。

另一种方法是对每个请求使用Promise.all() ,然后使用Promise.all()等待所有的asynchronous操作完成, Promise.all()也将为您收集所有结果。

像Async这样的nodejs库也有很多function来pipe理大量的asynchronous操作。


如果要序列化请求(实际上只有在前一个请求完成时才启动下一个请求),实际上它会更简单一些。 这可以这样做:

 function runAll() { var index = 2; function next() { if (index < process.argv.length) { http.get(process.argv[index], function (response) { response.pipe(bl(function (err, data) { console.log(data.toString()); ++index; next(); })); }); } } next(); } 

而且,这是一个使用承诺的版本,并行地运行请求,但是按顺序返回结果:

 var Promise = require('bluebird'); function runAll() { var promises = []; for (var i = 2; i < process.argv.length; i++) { promises.push(new Promise(function(resolve, reject) { http.get(process.argv[index], function (response) { response.pipe(bl(function (err, data) { resolve(data.toString()); })); }); })); } return Promise.all(promises); } runAll().then(function(resultArray) { // resultArray contains an array of the results from all the operations, in order for (var i = 0; i < resultArray.length; i++) { console.log(resultArray[i]); } });