重试异步/等待尝试并捕获块三遍,然后返回错误

时间:2019-03-18 14:47:44

标签: javascript node.js express async-await

发现了类似的问题,但没有一个回答我的问题。在抛出错误之前,我需要尝试运行3次异步函数。目前,它是通过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++
  }
}

问题之一是,当我这样做时,总是会出现以下错误:

  

UnhandledPromiseRejection警告:错误[ERR_HTTP_HEADERS_SENT]:将标头发送到客户端后无法设置标头

没有循环就不会出现。 所以我想问题是,如何在响应错误之前将这些调用限制为三个尝试?这是正确的路径还是还有另一种方法?为什么我的标题出现问题?

4 个答案:

答案 0 :(得分:2)

您应该像这样在res.json({ success: false, message: err && err.message })之后返回:

...
res.json({ success: false, message: err && err.message })
return
...

答案 1 :(得分:2)

是的,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))
})

答案 2 :(得分:1)

将重试逻辑移至异步功能,如下所示 这只是实现它的一个示例,可以根据需要进行调整。

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("...");
}

答案 3 :(得分:0)

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 })
}

外部捕获器处理重试三次并逃脱retry块的情况。您还可以设置一个onError函数,该函数具有针对每个错误(例如记录)执行的逻辑。