如何优化async.js API调用?

时间:2016-03-02 17:34:47

标签: javascript node.js async.js

我正在使用async.concat进行API调用。我正在使用它而不是其他async.js函数,因为:

一个。所有呼叫完成后,我需要在1个数组中得到结果

B中。 async.concat并行执行调用,这个程序的性能很重要

问题:似乎没有一种简单的方法来限制并发连接。该程序可能需要进行~100-300个不同的API调用(我无法在第一次API调用之前知道确切的#),而且我不想猛烈抨击服务器。

我考虑过:

  1. 将concat()嵌套在async.doWhilst()中,并一次执行5-10个块。但对于一个我确信之前有人解决过的问题,我觉得有点过于谨慎。

  2. 我还可以使用其中一个带有限制选项的异步函数,只需将每个结果推送到函数范围之上的数组。我是否应该担心多个API调用试图同时推送到同一个阵列?或者单线程是否意味着这不是问题?

  3. 还有其他简单的&这里有高效的途径吗?只要它很快并且我只剩下所有对象的1个阵列,我就会对大多数其他因素不感兴趣。

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