[英]Retry async/await try and catch block three times before responding with an error
发现了类似的问题,但都没有回答我的问题。 在抛出错误之前,我需要尝试运行异步函数三次。 目前用 while 循环来做,一开始就感觉不对。 这一切都发生在一条快速路线上。 这是我的代码目前的样子:
const MAX_NUMBER_OF_TRIES = 3
router.post('/', async function (req, res) {
let tries = 0
while (true) {
try {
await myAsyncFunction(body)
res.json({ success: true, message: 'Done!' })
} catch (err) {
if (tries >= MAX_NUMBER_OF_TRIES) {
res.json({ success: false, message: err && err.message })
}
}
tries++
}
}
问题之一是,当我这样做时,我总是收到以下错误:
UnhandledPromiseRejectionWarning: 错误 [ERR_HTTP_HEADERS_SENT]: 发送到客户端后无法设置标头
没有循环就不会出现这种情况。 所以我想问题是,如何在响应错误之前将这些调用限制为 3 次尝试? 这是正确的路径还是有其他方法可以做到? 为什么我会遇到标题问题?
你应该在res.json({ success: false, message: err && err.message })
像这样返回:
...
res.json({ success: false, message: err && err.message })
return
...
是的, while
循环看起来很粗略。 你永远不会阻止它。 只需使用普通循环即可。 当你得到回应时,你也需要休息。
const MAX_NUMBER_OF_TRIES = 3
router.post('/', async function (req, res) {
var message;
for (let tries = 0; tries < MAX_NUMBER_OF_TRIES; tries++) {
try {
await myAsyncFunction(body)
res.json({ success: true, message: 'Done!' })
return
// ^^^^^^
} catch (err) {
message = err && err.message;
console.log(`Try ${tries}: ${err}`)
}
}
res.json({ success: false, message })
}
这种奇怪的小控制流的替代方法是使用递归,它非常适合重试:
async function getResult(body, retries) {
try {
await myAsyncFunction(body)
return {success: true, message: 'Done'}
} catch(err) {
if (retries > 0)
return getResult(body, retries-1)
else
return {success: false, message: err && err.message}
}
}
const MAX_NUMBER_OF_TRIES = 3
router.post('/', async function (req, res) {
const RETRIES = MAX_NUMBER_OF_TRIES - 1
res.json(await getResult(body, RETRIES))
})
将重试逻辑移动到 async 函数,如下所示这只是一个如何实现的示例,请根据您的需要进行调整。
router.post('/', async function(req, res) {
try {
var result = await asyncFunc(3 /* retries */);
res.send(result);
} catch(ex)
{
res.send(ex);
}
})
在你的异步函数中,你可以实现类似的东西
async asyncFunc(retries)
{
for(var i = 0; i < retries; i++)
{
var result = await doSomething();
if(result)
{
// break the loop
return result;
}
}
// if we land here, so the number of retries was exceeded
throw Error("...");
}
async-retry包会为你做这件事; 代码量实际上最终是相似的,但它的功能要多一些,而且要正确使用也不那么繁琐。
例如:
const retry = require('async-retry')
try {
await retry(async () => {
await myAsyncFunction(body)
res.json({ success: true, message: 'Done!' })
}, {
retries: 3,
})
} catch (err) =>
{
res.json({ success: false, message: err && err.message })
}
外部 catch 处理它重试 3 次并逃脱retry
块的情况。 您还可以设置一个onError
函数,该函数具有要为每个错误(例如日志记录)执行的逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.