KOA --- 5. 全局异常处理

在开发中,为了及时的反馈信息,与前端对接好,异常处理,是后端必须去做的一种事情,反馈正确的信息,可以加快bug的解决
node中,由于基本都是异步方法,所以,为了能够处理好异步的异常,我们需要使用 async/await来解决
一、异常处理Demo
  • 由于中间件的特性,使得它可以用来作为全局异常处理的一个好途径
  • 为了代码的分离性,我们可以新建一个 专门存放中间件的文件夹middlewares,然后新建一个文件exception.js,用来存放异常处理的代码
  • 【KOA --- 5. 全局异常处理】exception.js
const catchError = async (ctx, next) => { try { await next() } catch (error) { ctx.body = '服务器错误' } }module.exports = catchError

  • 主文件引入app.js
// 引入并注册全局异常处理 // 注意:要放在代码前面,路由注册前面 const catchError = require('./middlewares/exception') app.use(catchError)

现在在路由文件抛出一个异常试试
throw new Error('API Exception')

使用posman发出请求试试
KOA --- 5. 全局异常处理
文章图片

返回了一个错误信息
二、定义异常类并运用 在后端编程中,面向对象的思想尤为重要,node也是如此,我们不妨将我们需要捕获到的异常编成一个个的异常类,需要的时候就抛出这个异常类,便更加的方便了
2.1、异常类的基类(父类) 首先,我们可以编写一个基类,来作为后面其他异常类的 父类,其他都可以基于这个类来延展开来
http-exception.js
/** * http 错误类型的 对象 */class HttpException extends Error { /** * 构造函数,可以设置默认值 * @param {返回的错误信息} msg * @param {错误编号} errorCode * @param {httpcode} code */ constructor(msg='服务器异常', errorCode=10000, code=400) { super() this.errorCode = errorCode this.code = code this.msg = msg }}module.exports = HttpException

2.2、简单使用一个这个异常类 找一个路由,设置你想要的一个参数,为它设置规范,如果传来的参数不符合这个规范,那么就会报错
classic.js
const Router = require('koa-router') const router = new Router() // 导入这个异常类 const HttpException = require('../../../core/http-exception')router.post('/v1/:id/classic/latest', async ctx => {const id = ctx.request.body.id// 如果这个参数没有传入,那么会报错 if(id) { const error = new HttpException('错误信息', 10001, 400) throw error }ctx.body = {key: 'calssic'}})// 3. 导出路由 module.exports = router

然后修改上面定义过的,处理异常的中间件``exception.js`
// 导入这个异常类 const HttpException = require('../core/http-exception')const catchError = async (ctx, next) => { // 尝试拦截错误 try {await next()} catch (error) {// 判断是否是定义过的错误类型 if(error instanceof HttpException) { ctx.body = { msg: error.msg, error_code: error.errorCode, request:`${ctx.method} ${ctx.path}` } ctx.status = error.code} } }module.exports = catchError

返回信息
KOA --- 5. 全局异常处理
文章图片

三、定义异常类的子类 3.1、定义参数 我们可以在这个异常类的基类延展开来,定义各种不同异常类的子类
例如:
  • 参数错误
  • 路径错误
  • 禁止访问
  • 未授权
  • 未找到资源
  • 等等
参数错误:ParameterException
/** * 参数错误 的异常类 */ class ParameterException extends HttpException { constructor(msg, errorCode) { super() this.code = 400 this.msg = msg || '参数错误' this.errorCode = errorCode || 10000 } }module.exports = { HttpException, ParameterException }

3.2、改写上面的Demo 在路由里面,我们将父类HttpException改为子类ParameterException
router.post('/v1/:id/classic/latest', async ctx => {const id = ctx.request.body.id// 如果这个参数没有传入,那么会报错 if(id) { const error = new ParameterException('参数未传递', 10001) throw error }ctx.body = {key: 'calssic'}})

效果也是一样的

    推荐阅读