我正在使用async.concat进行API调用。我正在使用它而不是其他async.js函数,因为:
一个。所有呼叫完成后,我需要在1个数组中得到结果
B中。 async.concat并行执行调用,这个程序的性能很重要
问题:似乎没有一种简单的方法来限制并发连接。该程序可能需要进行~100-300个不同的API调用(我无法在第一次API调用之前知道确切的#),而且我不想猛烈抨击服务器。
我考虑过:
将concat()嵌套在async.doWhilst()中,并一次执行5-10个块。但对于一个我确信之前有人解决过的问题,我觉得有点过于谨慎。
我还可以使用其中一个带有限制选项的异步函数,只需将每个结果推送到函数范围之上的数组。我是否应该担心多个API调用试图同时推送到同一个阵列?或者单线程是否意味着这不是问题?
还有其他简单的&这里有高效的途径吗?只要它很快并且我只剩下所有对象的1个阵列,我就会对大多数其他因素不感兴趣。
答案 0 :(得分:0)
根据您的需要,node'js
似乎是一个非常好的工具。如果您正在谈论~100-300 API请求,那么您在node
发出请求时会遇到问题,因此请求服务器(在这种情况下为node
)的阻塞不是一个问题。
但是,如果您正在对必须处理这些调用的同一服务器执行这些API调用,那么您可能会遇到问题,因此在这种情况下,如果请求的最佳数量,您应该批量调整批次数。 / p>
使用bluebird保证库:
// mock data
// supposing that this is the array of apis to call
var requestsToComplete = [c1, c2, c3, ..., c300];
var Promise = require('bluebird');
var results = [];
var fakeCounter = 0;
// fake api call... for demonstration purposes
function processApiCall(apiData) {
// simulate api call...
var promise = new Promise(function(resolve, reject) {
setTimeout(function() { resolve(fakeCounter++) });
});
return promise;
}
function processBatch(reqs, batchSize, skip) {
var batchRequests = [];
for (var i = skip; i < Math.min(i+batchSize, reqs.length); i++) {
var requestPromise = processApiCall(reqs[i]);
batchRequests.push(requestPromise);
}
// process all
return Promise.all(batchRequests);
}
function makeApiCalls() {
var batchCount = 0;
var batchSize = 10;
var promise = Promise.resolve();
while (batchCount < requestsToComplete.length) {
batchCount += batchSize;
promise = promise.then(function() {
return processBatch(requestsToComplete, batchSize, batchCount);
}).then(function(batchResponse) {
results = results.concat(batchResponse);
});
}
promise.then(function() {
// all api calls finished
// results now contain all the responses in order of calling, i.e.
results = [c1Response, c2Response, ..., c300Response];
// well, in our case results will be an array of fake results...
results = [0, 1, 2, ..., 300];
});
}
请注意,我的上述代码未经过测试,只是我将如何处理这种情况的一个示例。
但是,当然,如果同时调用所有300个端点不是问题,那么你可以这样做:
var promises = [];
for (... iterate through api endpoints) {
promises.push(processEndpoint(endpoints[i]));
}
Promise.all(promises).then(function (results) {
// results will be an array with each response, in order of calling
})