javascript - 如何优化 async.js API 调用?

标签 javascript node.js async.js

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

A.所有调用完成后,我需要将结果保存在 1 个数组中

B. async.concat 并行进行调用,该程序的性能很重要

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

我考虑过:

  1. 将 concat() 嵌套在 async.doWhilst() 中,并一次执行 5-10 个 block 。但对于我确信之前已经有人解决过的问题来说,这感觉有点太偷工减料了。

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

这里还有其他简单且高效的途径吗?只要它速度快并且我只剩下 1 个所有对象的数组,我对这里的大多数其他因素没有意见。

最佳答案

对于你所需要的,node'js似乎是一个很好的工具。如果您谈论的是大约 100-300 个 API 请求,那么从 node 发出请求不会有问题,因此攻击请求者服务器(在本例中为 node)不是问题。

但是,如果您对必须处理这些调用的同一服务器执行这些 API 调用,则可能会遇到问题,因此在这种情况下,您应该在最佳请求数量的情况下限制批量调用的数量。

使用bluebird promise 库:

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

关于javascript - 如何优化 async.js API 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35754263/

相关文章:

javascript - NodeJS 有 "require or download"的简写方法吗?

javascript - 如何用js设置cookies过期时间?

javascript - 如何将变量放入 PhantomJS 生成的 HTML 标题中以进行 PDF 转换?

node.js - Typescript 没有重载与此调用匹配

javascript - 如何在 Raspberry Pi 和远程托管 Web App 之间建立双向通信?

javascript - 从 typescript 中的 map 检索值时,map.get 不是函数

javascript - 删除 cookies chrome 扩展

mysql - 如何在 Node 中链接彼此依赖的sql查询

javascript - 在 javascript 中使用反射来获取失败时测试函数的名称

javascript - async.js - 正确的探测方法