有没有更好的方法来处理快递中的错误?

Posted

技术标签:

【中文标题】有没有更好的方法来处理快递中的错误?【英文标题】:Is there a better way to handle errors in express? 【发布时间】:2021-04-06 14:43:16 【问题描述】:

一段时间后,我正在快速构建一个 API。这个应用程序可以帮助用户跟踪他们的吉他套路。以下是我的控制器中的 DELETE 函数示例以及可能引发的异常:

 deleteOneRoutine = async (userId, routineId) => 
  // If the given routineId is found in the DB 
  // AND the userId matches, delete it from DB

  const selectedRoutine = await Routine.findOne(_id: routineId);
  if (!selectedRoutine) return 400;

  if (selectedRoutine.userId != userId) return 401;

  const deleted = await selectedRoutine.remove();
  if (!deleted) return 500;

  return deleted;

这是接收这些错误代码的路由:

  routineRouter.delete('/:routineId', async (req, res) => 
   const userId = req.params.userId;
   const routineId = req.params.routineId;
   const deleted = await routineController.deleteOneRoutine(userId, routineId);
   if (deleted === 400) res.status(400).send('Requested routine could not be found.')
   else if (deleted === 401) res.status(401).send('Unauthorized user.')
   else if (deleted === 500) res.status(500).send('Server error. Could not delete routine.')
   else res.status(200).send(`Successfully deleted routine with ID $routineId`)  
);

我想知道是否有更好的方法来处理这个问题,而不是手动从控制器传回错误代码。任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

在 Express 中抛出错误并添加错误处理程序会更容易。

router.use((err, req, res, next) => 
  res.status(500).send(err.message);
);

router.get('/path', async (req, res) => 
  throw new Error('Can't delete!');
);

我认为错误中间件必须先出现,但我必须检查。

如果你需要特定的错误类型,你可以继承 Error;如果您希望能够传递代码,则可以在错误上添加一个属性(尽管我建议避免将路由逻辑(例如设置特定的 HTTP 代码)与业务逻辑(例如您的 deleteOneRoutine 函数)混合)

【讨论】:

【参考方案2】:

我对返回值的当前类型不太满意——我认为返回一个带有错误属性中的错误或例程 ID 的对象会更有意义。但 IMO 更好的方法是传递 res 以便 deleteOneRoutine 可以自己完成。还要创建一个辅助函数来保持 DRY,并且不要忘记捕获异步函数抛出的可能异常:

deleteOneRoutine = async (userId, routineId, res) => 
  const send = (code, message) => res.status(code).send(message);
  const serverError = () => send(500, 'Server error. Could not delete routine.');
  try 
    const selectedRoutine = await Routine.findOne(_id: routineId);
    if (!selectedRoutine) return send(400, 'Requested routine could not be found.');
    if (selectedRoutine.userId !== userId) return send(401, 'Unauthorized user.');
    const deleted = await selectedRoutine.remove();
    if (!deleted) return serverError();
    send(200, `Successfully deleted routine with ID $deleted`);
   catch(e) 
    serverError();
  


routineRouter.delete('/:routineId', (req, res) => 
  const  userId, routineId  = req.params;
  routineController.deleteOneRoutine(userId, routineId, res);
);

【讨论】:

不要敲你的代码,但我认为让deleteOneRoutine“意识到”它的“网络上下文”会降低它的可重用性并导致更复杂的代码,最终成为天网并征服所有人类生命。

以上是关于有没有更好的方法来处理快递中的错误?的主要内容,如果未能解决你的问题,请参考以下文章

处理快递申请中未处理的承诺拒绝

更好的PHP错误处理

Golang 中更好的错误处理:理论和实践技巧

您将如何手动触发将错误从节点快递记录到哨兵?

有没有更好的方法来抑制赛普拉斯开玩笑测试顶部关于“三斜杠指令”的 ESLint 错误?

销售数字商品时 Paypal 快递结帐错误