如果您可以使用 Bluebird Promise库,它具有内置的并发功能,可让您管理一组异步操作,一次最多 N 个。
var Promise = require('bluebird');
const bigArray = [....];
Promise.map(bigArray, apiFetch, {concurrency: 20}).then(function(data) {
// all done here
});
这个接口的好处是它可以保持 20 个请求。它将启动 20,然后每完成一个,它就会启动另一个。因此,这可能比发送 20 个更有效,等待所有完成,再发送 20 个等等......
这也以完全相同的顺序提供结果,bigArray
以便您可以确定哪个结果与哪个请求相符。
当然,您可以使用计数器通过通用Promise自己编写代码,但由于它已经内置在 Bluebird 库中,我想我会推荐这种方式。
Async 库也有类似的并发控制,尽管它显然不是基于Promise的。
这是一个仅使用 ES6 promise 的手工编码版本,它维护结果顺序并始终保持 20 个请求在运行(直到没有 20 个请求)以获得最大吞吐量:
function pMap(array, fn, limit) {
return new Promise(function(resolve, reject) {
var index = 0, cnt = 0, stop = false, results = new Array(array.length);
function run() {
while (!stop && index < array.length && cnt < limit) {
(function(i) {
++cnt;
++index;
fn(array[i]).then(function(data) {
results[i] = data;
--cnt;
// see if we are done or should run more requests
if (cnt === 0 && index === array.length) {
resolve(results);
} else {
run();
}
}, function(err) {
// set stop flag so no more requests will be sent
stop = true;
--cnt;
reject(err);
});
})(index);
}
}
run();
});
}
pMap(bigArray, apiFetch, 20).then(function(data) {
// all done here
}, function(err) {
// error here
});
这里的工作演示:http : //jsfiddle.net/jfriend00/v98735uu/