速率限制问题,循环遍历动态 Promise 请求

Rate Limit Issue, looping through dynamic Promise requests

我在向 api 发送许多请求时遇到速率限制 429 的问题。我正在使用 api 的 Node.js 库来发出带有 Javascript es-6 Promises 的请求。

每个 Promise 都有两个参数,并且参数会根据每个请求而变化。

我已经通过将 promise 与 .then() 链接起来并包含一个延迟函数来解决速率限制问题,该函数 returns 在 ??ms 之后解决了 promise。

let delay = (time = delay_ms) => (result) => new Promise(resolve => setTimeout(() => resolve(result), time));

像这样:

request(arg1, arg2) .then(delay(300)) .then(request(arg1, arg2)) .then(delay(300))...

这解决了速率限制问题,但它让我不得不使用该解决方案编写大量代码,这让我非常头疼,因为我将不得不编写大量代码。

我希望 arg1arg2 存在于不同的数组中,这样我就可以遍历它们以动态构建承诺请求并在每个请求之间包含延迟。

我尝试使用 forEach 和 for 循环进行迭代,但所有请求都在彼此相隔几毫秒内触发,再次造成速率限制 429 问题。

是否有解决方案:

我的代码看起来像这样:

requestPromise(arg1_a, arg2_a).then(res => delay(ms)).then(requestPromise(arg1_b, arg2_b)).then(res => delay(ms))...

对异步等待有什么帮助吗?我试过了,但我似乎无法解决这个问题?可能是由于 Promises 和动态参数???不确定我是否了解如何将异步等待与动态 Promise 和迭代等结合起来...

感谢任何帮助。

如果我正确理解了您要查找的内容,您希望在每个请求之间延迟遍历数组,调用 requestPromise(x, y),其中 xy 来自每个数组。

你可以这样做:

const delay_ms = 100;

function delay(t = delay_ms) {
    return new Promise(resolve => {
        setTimeout(resolve, t);
    });
}

function iterate(a1, a2, t) {
    let index = 0;
    const len = Math.min(a1.length, a2.length);
    if (len === 0) {
        return Promise.reject(new Error("iterate(a1, a2, t) needs two non-zero length arrays"));
    }

    function run() {
        return requestPromise(a1[index], a2[index]).then(() => {
            index++;
            // if still more to process, insert delay before next request
            if (index < len) {
                return delay(t).then(run);
            }
        });
    }

    return run();
}

// sample usage
let arr1 = ['USD', 'EUR' ...];
let arr2 = [60, 300, 600 ...];

iterate(arr1, arr2, 500).then(() => {
    // all done here
}).catch(err => {
    // got error here
});

这是通过创建一个承诺链来实现的,其中每个新请求都链接到先前的承诺链上,并且仅在延迟后执行。通过初始化为 0index 变量访问数组,然后在每次迭代后递增。

此函数需要两个非零长度数组,并将迭代到两个数组中较短的一个的长度(如果由于某种原因它们的长度不相等)。

Promises.all() 可用于处理来自异步调用的承诺的 returns 但是为了处理并发请求的数量,http.request 代码需要限制数量的电话。设置 https.globalAgent.maxSocket = 20 对我来说是一个简单的解决方法。这显然是在向节点客户端发出请求时使用的。

使用 async/await 和标准 for 循环应该非常简单。

async function iterate(arr1, arr2) {
    for (let i = 0; i < arr1.length; i++) {
        await requestPromise(arr1[i], arr2[i]);
        await delay(300);
    }
}

let arr1 = ['USD', 'EUR'];
let arr2 = [60, 300, 600];
iterate(arr1, arr2);

此实现假定数组的长度相同。