async/await 使用 Limiter 发送请求
async/await with Limiter for sending requests
我正在尝试限制发送给 API 的请求数量。
我正在使用 Limiter,它的工作方式和我需要的一样,唯一的问题是我找不到将它与 await 一起使用的方法(在呈现我的页面之前我需要所有响应)
有人可以帮助我吗?
顺便说一句,日志 returns 一个布尔值。
const RateLimiter = require('limiter').RateLimiter;
const limiter = new RateLimiter(50, 5000)
for (let i = 0; i < arrayOfOrders.length; i++) {
const response = limiter.removeTokens(1, async (err, remainingRequests) => {
console.log('request')
return await CoreServices.load('updateOrder', {
"OrderNumber": arrayOfOrders[i],
"WorkFlowID": status
})
})
console.log('response', response)
}
console.log('needs to log after all the request');
这是登录:
response true
response true
response false
needs to log after all the request
request
request
request
...
承诺 .removeTokens
会有所帮助,看看这段代码是否有效
const RateLimiter = require('limiter').RateLimiter;
const limiter = new RateLimiter(50, 5000);
const tokenPromise = n => new Promise((resolve, reject) => {
limiter.removeTokens(n, (err, remainingRequests) => {
if (err) {
reject(err);
} else {
resolve(remainingRequests);
}
});
});
(async() => { // this line required only if this code is top level, otherwise use in an `async function`
const results = await Promise.all(arrayOfOrders.map(async (order) => {
await tokenPromise(1);
console.log('request');
return CoreServices.load('updateOrder', {
"OrderNumber": order,
"WorkFlowID": status
});
}));
console.log('needs to log after all the request');
})(); // this line required only if this code is top level, otherwise use in an `async function`
说明
首先:
const tokenPromise = n => new Promise((resolve, reject) => {
limiter.removeTokens(n, (err, remainingRequests) => {
if (err) {
reject(err);
} else {
resolve(remainingRequests);
}
});
});
promisifies limiter.removeTokens
在 async/await 中使用 - 在 nodejs 中你可以使用内置的 promisifier,但是最近我有太多失败的例子 - 所以手动 promisification(我我在这里编造了很多单词!)同样有效
现在代码很简单 - 您可以使用 arrayOfOrders.map
而不是 for 循环来创建一个承诺数组,所有 运行 都在速率限制允许的范围内并行,(速率限制在回调中完成)
await Promise.all(...
将等到所有 CoreServices.load
完成(或者一个失败 - 如果需要,您可以使用 await Promise.allSettled(...
)
地图回调中的代码被标记为async
所以:
await tokenPromise(1);
将等到调用 removeTokens
回调 - 然后请求
return CoreServices.load
制作
注意,这最初是 return await CoreServices.load
但 await 是多余的,因为异步函数中的 return await somepromise
与 return somepromise
相同 - 所以,也要调整你的代码
我正在尝试限制发送给 API 的请求数量。
我正在使用 Limiter,它的工作方式和我需要的一样,唯一的问题是我找不到将它与 await 一起使用的方法(在呈现我的页面之前我需要所有响应)
有人可以帮助我吗?
顺便说一句,日志 returns 一个布尔值。
const RateLimiter = require('limiter').RateLimiter;
const limiter = new RateLimiter(50, 5000)
for (let i = 0; i < arrayOfOrders.length; i++) {
const response = limiter.removeTokens(1, async (err, remainingRequests) => {
console.log('request')
return await CoreServices.load('updateOrder', {
"OrderNumber": arrayOfOrders[i],
"WorkFlowID": status
})
})
console.log('response', response)
}
console.log('needs to log after all the request');
这是登录:
response true
response true
response false
needs to log after all the request
request
request
request
...
承诺 .removeTokens
会有所帮助,看看这段代码是否有效
const RateLimiter = require('limiter').RateLimiter;
const limiter = new RateLimiter(50, 5000);
const tokenPromise = n => new Promise((resolve, reject) => {
limiter.removeTokens(n, (err, remainingRequests) => {
if (err) {
reject(err);
} else {
resolve(remainingRequests);
}
});
});
(async() => { // this line required only if this code is top level, otherwise use in an `async function`
const results = await Promise.all(arrayOfOrders.map(async (order) => {
await tokenPromise(1);
console.log('request');
return CoreServices.load('updateOrder', {
"OrderNumber": order,
"WorkFlowID": status
});
}));
console.log('needs to log after all the request');
})(); // this line required only if this code is top level, otherwise use in an `async function`
说明
首先:
const tokenPromise = n => new Promise((resolve, reject) => {
limiter.removeTokens(n, (err, remainingRequests) => {
if (err) {
reject(err);
} else {
resolve(remainingRequests);
}
});
});
promisifies limiter.removeTokens
在 async/await 中使用 - 在 nodejs 中你可以使用内置的 promisifier,但是最近我有太多失败的例子 - 所以手动 promisification(我我在这里编造了很多单词!)同样有效
现在代码很简单 - 您可以使用 arrayOfOrders.map
而不是 for 循环来创建一个承诺数组,所有 运行 都在速率限制允许的范围内并行,(速率限制在回调中完成)
await Promise.all(...
将等到所有 CoreServices.load
完成(或者一个失败 - 如果需要,您可以使用 await Promise.allSettled(...
)
地图回调中的代码被标记为async
所以:
await tokenPromise(1);
将等到调用 removeTokens
回调 - 然后请求
return CoreServices.load
制作
注意,这最初是 return await CoreServices.load
但 await 是多余的,因为异步函数中的 return await somepromise
与 return somepromise
相同 - 所以,也要调整你的代码