如何在异步等待调用节点上设置超时



如何将 setTimeout 添加到我的异步等待函数调用中?

我有

request = await getProduct(productids[i]);

哪里

const getProduct = async productid => {
return requestPromise(url + productid);
};

我试过了

request = await setTimeout((getProduct(productids[i])), 5000);

并得到了错误TypeError: "callback" argument must be a function这是有道理的。该请求位于一个循环中,这使我达到了 api 调用的速率限制。

exports.getProducts = async (req, res) => {
let request;
for (let i = 0; i <= productids.length - 1; i++) {
request = await getProduct(productids[i]);
//I want to wait 5 seconds before making another call in this loop!
}
};

您可以使用一个简单的小函数,该函数返回在延迟后解析的承诺:

function delay(t, val) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(val);
}, t);
});
}
// or a more condensed version
const delay = (t, val) => new Promise(resolve => setTimeout(resolve, t, val));

然后,在循环中await它:

exports.getProducts = async (req, res) => {
let request;
for (let id of productids) {
request = await getProduct(id);
await delay(5000);
}
};

注意:我还切换了您的for循环以使用for/of这不是必需的,但比您拥有的要干净一些。


或者,在nodejs的现代版本中,您可以使用timersPromises.setTimeout(),这是一个返回承诺的内置计时器(从nodejs v15开始(:

const setTimeoutP = require('timers/promises').setTimeout;
exports.getProducts = async (req, res) => {
let request;
for (let id of productids) {
request = await getProduct(id);
await setTimeoutP(5000);
}
};

实际上,我有一个非常标准的代码块,我用来做到这一点:

function PromiseTimeout(delayms) {
return new Promise(function (resolve, reject) {
setTimeout(resolve, delayms);
});
}

用法:

await PromiseTimeout(1000);

如果您使用的是蓝鸟承诺,那么它是内置的Promise.timeout.

更多关于您的问题:您是否检查过 API 文档?一些 API 会告诉您在下一个请求之前需要等待多少时间。或者允许批量下载数据。

从节点 v15 开始,您可以使用计时器承诺 API:

const timersPromises = require('timers/promises');
async function test() {
await timersPromises.setTimeout(1000);
}
test();

请注意,此功能是实验性的,可能会在将来的版本中更改。

从 Node 15 及更高版本开始,有了新的计时器承诺 API,可让您避免构建包装:

import {
setTimeout,
setImmediate,
setInterval,
} from 'timers/promises';
console.log('before')
await setTimeout(1000)
console.log('after 1 sec')

所以你的问题你可以用异步迭代器来写它:

import {
setTimeout
} from 'timers/promises'
async function getProducts (req, res) {
const productids = [1, 2, 3]
for await (const product of processData(productids)) {
console.log(product)
}
}
async function * processData (productids) {
while (productids.length > 0) {
const id = productids.pop()
const product = { id }
yield product
await setTimeout(5000)
}
}
getProducts()

我已经做了如下 api 延迟测试。 可以像挂起 setTimeout 一样延迟它。

sleep(ms) {
const wakeUpTime = Date.now() + ms;
while (Date.now() < wakeUpTime) {}
}
callAPI = async() => {
...  // Execute api logic 
await this.sleep(2147483647);
...  // Execute api logic 
}
await callAPI();

最新更新