首页 > 解决方案 > 处理每条 Express 路线上的异常情况

问题描述

我想对每条路由进行一些基本的错误处理,所以如果有异常,API 至少会响应 500。

根据这种模式,您仍然需要try/catch在每条路线中包含一个块:

app.post('/post', async (req, res, next) => {
  const { title, author } = req.body;
  
  try {
    if (!title || !author) {
      throw new BadRequest('Missing required fields: title or author');
    }
    const post = await db.post.insert({ title, author });
    res.json(post);
  } catch (err) {
    next(err) // passed to the error-handling middleware
  }
});

这似乎有点重复。是否有一种更高级别的方式可以在任何地方自动捕获异常并将其传递给中间件?

我的意思是,我显然可以定义我自己的appGet()

function appGet(route, cb) {
    app.get(route, async (req, res, next) => {
        try {
          await cb(req, res, next);
        } catch (e) {
            next(e);
        }
    });
}

是否有一些内置版本?

标签: node.jsexpresserror-handlingmiddleware

解决方案


我认为更好的方法是划分服务和控制器,如下所示。

添加邮政服务:

async function addPostService (title, author) => {
    if (!title || !author)
      throw new BadRequest('Missing required fields: title or author');
    
    return await db.post.insert({ title, author });
};

添加后期控制器:

function addPost(req, res, next){
    const { title, author }= req.body;

    addPostService
      .then((post) => {
        res.json(post);
      })
      .catch(next) // will go through global error handler middleware
}

现在,我们可以创建一个全局错误处理程序中间件,该中间件将捕获整个应用程序中任何控制器抛出的错误。

function globalErrorHandler(err, req, res, next){
  switch(true){
    case typeof err === 'string':
      // works for any errors thrown directly
      // eg: throw 'Some error occured!';
      return res.status(404).json({ message: 'Error: Not found!'});
    
    // our custom error
    case err.name = 'BadRequest':
      return res.status(400).json({ message: 'Missing required fields: title or author!'})
    
    default:
      return res.status(500).json({ message: err.message });
  }
}

而且,不要忘记在启动服务器之前使用错误处理程序中间件。

// ....
app.use(globalErrorHandler);
app.listen(port, () => { console.log('Server started...')});

推荐阅读