我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

Express中间件如果抛出了错误,那么,在对应的路由内部是无法捕获错误的。因为,路由内部的逻辑是直接越过的。直接走向express请求结束。那么,本文就这种情况进行简单的讨论。如何全局捕获express的错误信息呢?包括路由内部以及中间件里面的错误信息。

苏南大叔:Express,通过中间件,如何全局捕获错误?改写异常结果 - 中间件全局捕获错误
Express,通过中间件,如何全局捕获错误?改写异常结果(图5-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:nodejs@20.18.0,express@4.21.2jsonwebtoken@9.0.2express-jwt@8.5.1。本文说的是express错误全局掌控,不管哪里抛出了错误,都能捕捉到,并做出调整。

用魔法解决魔法

Express,可能会抛出错误的地方,有三个:

  • 路由逻辑内部,可捕获。
  • 中间件内部,可捕获。
  • 路由定义外部,代码顶层。但是这种情况下,express也运行不起来。

用中间件来捕获中间件的错误,重点就是【用来捕获的中间件的位置】,建议把它放在所有路由的最后面。下面中间件的代码位置,将部分影响本文的结论。

app.use((err, req, res, next) => {
  console.log(req.url);      // /refresh
  console.log(req.method);   // get
  // ...
  console.log(err.name);     // UnauthorizedError
  console.log(err.code);     // invalid_token
  console.log(err.status);   // 401
  console.log(err.message);  // jwt malformed
  // ...
});

后续逻辑走向可以使用的依据,就是reqerr。如果是个自定义的错误类型,就可以通过其.name进行判断。本文的目标错误类型就是UnauthorizedError,它就是express-jwt中间件所发出的错误异常名称。

方案一,抛出一个新的异常

只是修改一下错误代码和消息,抛出一个被修改的错误。

res.status(401).send("无效的Token");

例如:

app.use((err, req, res, next) => {
  if (err.name === "UnauthorizedError") {
    return res.status(401).send("无效的Token");
  }
  return res.status(500).send("未知错误");
});

苏南大叔:Express,通过中间件,如何全局捕获错误?改写异常结果 - 抛出另外一个异常
Express,通过中间件,如何全局捕获错误?改写异常结果(图5-2)

方案二,正常输出json【推荐】

截获错误的目的,就是最大限度的保证服务器端的异常代码(非200状态码)。所以,推荐使用这个方案。把标红的异常请求,转化为普通的200请求。

return res.send({
  status: 401,
  message: "无效的Token",
});

例如:

app.use((err, req, res, next) => {
  if (err.name === "UnauthorizedError") {
    return res.send({
      status: 401,
      message: "无效的Token",
    });
  }
  return res.send({
    status: 500,
    message: "未知错误",
  });
});

苏南大叔:Express,通过中间件,如何全局捕获错误?改写异常结果 - 修改异常为正常
Express,通过中间件,如何全局捕获错误?改写异常结果(图5-3)

这个例子的返回值,很容易误导大家得到的是个error。所以,实际应用的时候,可以做些变通。

方案三,next()转下一个路由

正常的走向下一个逻辑,期待后面还有个能处理请求的路由。

  • 如果本文所述中间件,位于所有的路由的最后方的话,下一个逻辑就只能是404 not found了。
  • 如果本文所述中间件,后面还有一个能承载的路由的话,那么也许还能处理。
next()

苏南大叔:Express,通过中间件,如何全局捕获错误?改写异常结果 - 错误转下一个路由
Express,通过中间件,如何全局捕获错误?改写异常结果(图5-4)

方案四,next(err)转下一个中间件

带着err走向下一个逻辑,期待后面还有个能处理err的中间件。

next(err)

为了捕获错误,已经把这个中间件安排到所有路由的最后面了。所以,next()的话,也是个404的结果。但是,如果把这段异常捕获中间件,放在路由定义的中间,这个next()还是有可能匹配到新的代码逻辑的。这个时候,next()就有些意义。

苏南大叔:Express,通过中间件,如何全局捕获错误?改写异常结果 - 中间件往后继续传递错误
Express,通过中间件,如何全局捕获错误?改写异常结果(图5-5)

题外话

所以,express里面,定义两个相同路由,并不会产生覆盖关系。但是,也不会产生先后执行的关系。除非由这种错误捕获中间件,进行串联,后续再讨论吧。

相关文章

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   express