如何优化 async.js API 调用?
How can I optimize async.js API calls?
我正在使用 async.concat 进行 API 通话。我使用这个而不是其他 async.js 函数,因为:
一个。所有调用完成后,我需要 1 个数组中的结果
乙。 async.concat 进行并行调用,性能对这个程序很重要
问题:似乎没有一种简单的方法来限制并发连接。该程序可能需要进行 ~100-300 次不同的 API 调用(我无法在第一次 API 调用之前知道确切的 #),而且我不想关闭服务器。
我考虑过:
将 concat() 嵌套在 async.doWhilst() 中,并一次执行 5-10 个块。但是对于一个我确定有人已经解决过的问题来说,这感觉有点过于草率了。
我还可以使用带有 Limit 选项的异步函数之一,并将每个结果简单地推送到函数作用域上方的数组中。我是否应该担心多个 API 调用试图同时推送到同一个数组?还是单线程意味着这不是问题?
这里还有其他简单且高效的途径吗?只要它很快并且我只剩下 1 个所有对象数组,我对这里的大多数其他因素都没有意见。
对于您所需要的,node'js
似乎是一个很好的工具。如果您谈论的是 ~100-300 API 请求,那么从 node
发出请求不会有问题,因此抨击请求者服务器(在本例中为 node
)不是一个问题。
但是,如果您对必须处理这些调用的同一台服务器执行那些 API 调用,您可能会遇到问题,因此在这种情况下,如果最佳数量,您应该限制批量调用的数量请求数。
使用 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
})
我正在使用 async.concat 进行 API 通话。我使用这个而不是其他 async.js 函数,因为:
一个。所有调用完成后,我需要 1 个数组中的结果
乙。 async.concat 进行并行调用,性能对这个程序很重要
问题:似乎没有一种简单的方法来限制并发连接。该程序可能需要进行 ~100-300 次不同的 API 调用(我无法在第一次 API 调用之前知道确切的 #),而且我不想关闭服务器。
我考虑过:
将 concat() 嵌套在 async.doWhilst() 中,并一次执行 5-10 个块。但是对于一个我确定有人已经解决过的问题来说,这感觉有点过于草率了。
我还可以使用带有 Limit 选项的异步函数之一,并将每个结果简单地推送到函数作用域上方的数组中。我是否应该担心多个 API 调用试图同时推送到同一个数组?还是单线程意味着这不是问题?
这里还有其他简单且高效的途径吗?只要它很快并且我只剩下 1 个所有对象数组,我对这里的大多数其他因素都没有意见。
对于您所需要的,node'js
似乎是一个很好的工具。如果您谈论的是 ~100-300 API 请求,那么从 node
发出请求不会有问题,因此抨击请求者服务器(在本例中为 node
)不是一个问题。
但是,如果您对必须处理这些调用的同一台服务器执行那些 API 调用,您可能会遇到问题,因此在这种情况下,如果最佳数量,您应该限制批量调用的数量请求数。
使用 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
})