阅读 241

EggJS-统一错误处理

得益于框架支持的异步编程模型,错误完全可以用 try catch 来捕获。在编写应用代码时,所有地方都可以直接用 try catch 来捕获异常。

// app/service/test.js try {   const res = await this.ctx.curl('http://eggjs.com/api/echo', { dataType: 'json' });   if (res.status !== 200) throw new Error('response status is not 200');   return res.data; } catch (err) {   this.logger.error(err);   return {}; } 复制代码

按照正常代码写法,所有的异常都可以用这个方式进行捕获并处理,但是一定要注意一些特殊的写法可能带来的问题。打一个不太正式的比方,我们的代码全部都在一个异步调用链上,所有的异步操作都通过 await 串接起来了,但是只要有一个地方跳出了异步调用链,异常就捕获不到了。

// app/controller/home.js class HomeController extends Controller {   async buy () {     const request = {};     const config = await ctx.service.trade.buy(request);     // 下单后需要进行一次核对,且不阻塞当前请求     setImmediate(() => {       ctx.service.trade.check(request);     });   } } 复制代码

在这个场景中,如果 service.trade.check 方法中代码有问题,导致执行时抛出了异常,尽管框架会在最外层通过 try catch 统一捕获错误,但是由于 setImmediate 中的代码『跳出』了异步链,它里面的错误就无法被捕捉到了。因此在编写类似代码的时候一定要注意。

当然,框架也考虑到了这类场景,提供了 ctx.runInBackground(scope) 辅助方法,通过它又包装了一个异步链,所有在这个 scope 里面的错误都会统一捕获。

class HomeController extends Controller {   async buy () {     const request = {};     const config = await ctx.service.trade.buy(request);     // 下单后需要进行一次核对,且不阻塞当前请求     ctx.runInBackground(async () => {       // 这里面的异常都会统统被 Backgroud 捕获掉,并打印错误日志       await ctx.service.trade.check(request);     });   } } 复制代码

为了保证异常可追踪,必须保证所有抛出的异常都是 Error 类型,因为只有 Error 类型才会带上堆栈信息,定位到问题。

框架层统一异常处里

尽管框架提供了默认的统一异常处理机制(dev 会显示堆栈信息),但是应用开发中经常需要对异常时的响应做自定义,特别是在做一些接口开发的时候。框架自带的 onerror 插件支持自定义配置错误处理方法,可以覆盖默认的错误处理方法。

// config/config.default.js module.exports = {   onerror: {     all(err, ctx) {       // 在此处定义针对所有响应类型的错误处理方法       // 注意,定义了 config.all 之后,其他错误处理方法不会再生效       ctx.body = 'error';       ctx.status = 500;     },   }, }; 复制代码

404

框架并不会将服务端返回的 404 状态当做异常来处理,但是框架提供了当响应为 404 且没有返回 body 时的默认响应。

  • 当请求被框架判定为需要 JSON 格式的响应时,会返回一段 JSON:

{ "message": "Not Found" } 复制代码

  • 当请求被框架判定为需要 HTML 格式的响应时,会返回一段 HTML:

<h1>404 Not Found</h1> 复制代码

框架支持通过配置,将默认的 HTML 请求的 404 响应重定向到指定的页面。

// config/config.default.js module.exports = {   notfound: {     pageUrl: '/404.html',   }, }; 复制代码

自定义404响应

在一些场景下,我们需要自定义服务器 404 时的响应,和自定义异常处理一样,我们也只需要加入一个中间件即可对 404 做统一处理:

// app/middleware/notfound_handler.js module.exports = () => {   return async function notFoundHandler(ctx, next) {     await next();     if (ctx.status === 404 && !ctx.body) {       if (ctx.acceptJSON) {         ctx.body = { error: 'Not Found' };       } else {         ctx.body = '<h1>Page Not Found</h1>';       }     }   }; }; 复制代码

在配置中引入中间件:

// config/config.default.js module.exports = {   middleware: [ 'notfoundHandler' ], };


作者:Nordon
链接:https://juejin.cn/post/7064397410880978958

文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐