【问题标题】: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}`)}  
});

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

【问题讨论】:

    标签: javascript node.js express api-design


    【解决方案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“意识到”它的“网络上下文”会降低它的可重用性并导致更复杂的代码,最终成为天网并征服所有人类生命。
      猜你喜欢
      • 1970-01-01
      • 2018-08-22
      • 2011-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      相关资源
      最近更新 更多