对API调用队列进行速率限制并返回结果 [英] Rate limiting a queue of API calls and returning the results

查看:169
本文介绍了对API调用队列进行速率限制并返回结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在遍历一个数组,并使用async/await对每个成员进行API调用,然后将结果推送到另一个数组中,并返回该数组.

I'm looping through an array and making an API call for each member using async/await, I then push the result into another array which is returned.

// My current function
async requestForEach(repos) {
    const result = [];
    for (const repo of repos) {
        result.push(await this.doSomething(repo.name));
    }
    return result;
}

// doSomething()
const AWS = require('aws-sdk');
const codecommit = new AWS.CodeCommit();
async doSomething(repoName){
    return (await codecommit.listBranches({
        repoName
    }).promise()).branches;
}

我的问题是速率受到限制.如果我发现并打印错误,我就会得到..

My issue is I'm getting rate limited. If I catch and print the error I get..

ThrottlingException: Rate exceeded {
  // Call stack here
  code: 'ThrottlingException',
  time: 2020-08-16T15:52:56.632Z,
  requestId: '****-****-****-****-****',
  statusCode: 400,
  retryable: true
}

我正在使用的API的文档可在此处找到-

Documentation for the API I'm using can be found here - https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CodeCommit.html#listBranches-property

我研究了选项,并且这个异步库似乎是流行的选项.

I looked into options and this async library seemed to be the popular option.

使用async.queue().

Using async.queue()..

添加到队列中的任务将并行处理(直到 并发限制).如果所有工作人员都在进行中,则将任务排队 直到有空.工人完成一项任务后, 任务的回调被调用.

Tasks added to the queue are processed in parallel (up to the concurrency limit). If all workers are in progress, the task is queued until one becomes available. Once a worker completes a task, that task's callback is called.

// create a queue object with concurrency 2
var q = async.queue(function(task, callback) {
    console.log('hello ' + task.name);
    callback();
}, 2);

很明显,我无法从回调函数中获取值,那么该如何解决这个问题?

Obviously I cant get the value back from within the callback function, so how should I approach this problem?

推荐答案

连续的for … of循环对我来说看起来不错.您可以为每次迭代添加默认延迟以使其变慢,但是您也可以稍后在请求失败时重试请求,因为节流的.请注意,只有当您的应用程序中只有一个请求源(没有对requestForEach的多个并发调用)时,此方法才行得通,否则您可能需要全局协调.

The sequential for … of loop looks good to me. You can add a default delay for each iteration to make it slower, but you can also simply retry requests later when they fail because of throttling. Notice that this approach only works well when you have only a single source of requests in your app (not multiple concurrent calls to requestForEach), otherwise you'd probably need global coordination.

async doSomething(repoName) {
    while (true) {
        try {
            const data = await codecommit.listBranches({
                repoName
            }).promise();
            return data.branches;
        } catch(err) {
            if (err.code == 'ThrottlingException') { // if (err.retryable) {
                await delay(err.retryDelay ?? 1000);
                continue;
            } else {
                throw err;
            }
        }
    }
}
function delay(time) {
    return new Promise(resolve => {
        setTimeout(resolve, time);
    });
}

代替while (true)循环,递归方法可能看起来更好.请注意,在生产代码中,您将希望限制重试次数,以使循环永远不会无限运行.

Instead of the while (true) loop a recursive approach might look nicer. Notice that in production code you'll want to have a limit on the number of retries so that your loop never runs infinitely.

这篇关于对API调用队列进行速率限制并返回结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆