原标题:koa中如何优雅地处理异常和错误
一
异常和错误的抛出
1、常见抛出异常和错误类型:
● 代码语法不规范造成的JS报错异常
● 程序运行中发生的一些未知异常
● HTTP错误
● 自定义的业务逻辑错误
2、不优雅的方式
koa框架提供了ctx.throw(400)的方式,可以让我们方便地抛出http错误,但是如果你想同时返回一些有用信息怎么办?也许你会这么做:
ctx.status = 400
ctx.body = {
msg: "参数错误"
}
若需要定义若干业务逻辑错误码和说明,返回不同的code,在controller层面,你也许可以这样处理:
router.get('/', (ctx, next) => {
if (tokenExpire(token)) {
const errcode = ERROR_CODE.TOKEN_EXPIRED
ctx.body = {
errcode,
msg: ERROR_MSG[errcode]
}
return
}
// do something
})
如果是在model层或者server层,要处理这样的错误怎么办?
通过定义返回值来说明错误,在controller中判断返回值再返回相应错误码,比如:
router.get('/', (ctx, next) => {
if (tokenExpire(token)) {
const errcode = ERROR_CODE.TOKEN_EXPIRED
ctx.body = {
errcode,
msg: ERROR_MSG[errcode]
}
return
}
// do something
})
抛出Error,在controller中catch住异常,并对比err.message来返回相应错误码,比如:
const somefunc = async (token) => {
const res = await tokenExpire(token)
if (res) {
throw Error(ERROR_MSG.TOKEN_EXPIRED)
}
// do something
}
二
异常的捕获
1、error事件的监听方式:
const Koa = require('koa')
const app = new Koa()
app.on('error', (err, next) => {
console.error('server error',err)
})
const main = ctx => {
ctx.throw(500)
}
app.use(main)
app.listen(3000)
2、重载app.context.方法的方式:
const Koa = require('koa')
const app = new Koa()
app.context. = function(err){
console.error('server error1',err)
}
const main = ctx => {
ctx.throw(500)
}
app.use(main)
app.listen(3000)
3、中间件的处理方式:
const Koa = require('koa')
const app = new Koa()
app.use( async (ctx, next) =>{
await next().catch(error => {
console.log(error)
});
})
const main = ctx => {
ctx.throw(500)
}
app.use(main)
app.listen(3000)
三
更优雅的方式
目标:我们希望无论在哪里,直接一行代码就可以抛出错误,并被正确处理,返回相应的错误码和信息。
方案:自定义的继承于Error构造器的方法,利用koa中间件catch住错误,并统一把返回值做处理。
1、定义继承于Error构造器的方法CustomError
function CustomError(code, msg) {
Error.call(this, '');
if (arguments.length === 1 && typeof arguments[0] == 'string') {
msg = arguments[0];
code = 300;
}
this.code = code;
this.msg = msg || ERROR_MSG[code] || '发生了一个致命错误!';
this.getCodeMsg = function () {
return { code: this.code, msg: this.msg }
}
}
util.inherits(CustomError, Error);// 对象原型继承
2、抛出错误
const somefunc = async (token) => {
const res = await tokenExpire(token)
if (res) {
throw new CustomError(CUSTOM_CODE.SOME_CUSTOM_ERROR)
}
// do something
}
3、koa中间件统一catch住Error,并返回相应code,msg
app.use((ctx, next) => {
return next().catch((err) => {
let code = 500
let msg = 'unknown error'
if (err instanceof CustomError || err instanceof HttpError) {
const res = err.getCodeMsg()
ctx.status = err instanceof HttpError ? res.code : 200
code = res.code
msg = res.msg
} else {
console.error('err', err)
}
ctx.body = { code, msg }
})
})
四
koa-的介绍
1、koa-的使用
npm install koa-
const fs = require('fs');
const koa = require('koa');
const = require('koa-');
const app = new koa();
(app);
app.use(ctx => {
// foo();
ctx.body = fs.createReadStream('not exist');
});
2、参数介绍
●all: 设置后其他选项失效
● text: 返回类型为text的处理函数
● json: 返回类型为json的处理函数
● html: 返回类型为html的处理函数
● redirect: 如果返回类型是html,则可以添加在跳转
3、Options的使用示例
const fs = require('fs');
const koa = require('koa');
const = require('koa-');
const app = new koa();
(app, {
json(ctx, error) {
ctx.body = {code: error.status, msg: error.message}
}
});
app.use(ctx => {
// foo();
ctx.body = fs.createReadStream('not exist');
责任编辑: