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



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

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 请求,依此类推。但问题仍然存在,它执行顺序不对。不按用户请求的顺序排列。

我做错了什么?

如果您只是尝试按顺序记录结果,但希望请求并行运行,那么通常的解决方案是在数组中收集结果,然后在所有请求完成后输出结果。

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,然后使用 Promise.all() 等待所有异步操作完成,Promise.all() 还将为您收集所有结果。

而且,像 Async 这样的 nodejs 库也具有许多用于管理大量异步操作的功能。


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

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();
}

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

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]);
    }
});

相关内容

  • 没有找到相关文章