为什么要用错误处理?
1.防止程序 down 掉
2.告诉用户错误信息
3.便于开发者调试
错误处理是开发中非常重要的一部分,因为它可以帮助我们有效地处理潜在的错误情况
javascript 中错误处理的语法就是 try…catch
koa2 自带的错误处理也是 try…catch 实现的, 里面的源码是 catch 了一个 promise
一、错误处理方式
原生错误处理
在koa中处理错误情况,应该将错误处理中间件放在第一的位置,可以捕获后面所有中间件里面的错误信息,避免下面要执行的中间件单独处理异常。
app.use(async (ctx,next) => {
try {
await next();
} catch (err) {
ctx.status = err.status || err.statusCode;
ctx.body = {
message: err.message
}
}
})
可以捕获手动抛出的信息以及运行时报错信息而且是 json 格式,
优化了 koa 默认的错误处理,但是404 错误目前捕捉不到
使用 app.on 监听器
在 Koa 中,一些特定的事件可以被触发,例如错误事件(error)和服务器关闭事件(close)。当这些事件发生时,可以通过注册对应的监听器来处理它们。通过on进行统一错误处理,app.on 是用于注册事件监听器的。
// 该代码放在最后
app.on('error', (err, ctx) => {
console.error(err)
ctx.body = err
})
使用中间件处理错误
市面上有很多专门处理错误的中间件,这里我讲的是koa-onerror,这是koa脚手架koa-generator自带的处理错误中间件。
koa-onerror的用法如下:
-
安装koa-onerror模块:
npm install koa-onerror
-
导入koa-onerror模块:
const onError = require('koa-onerror');
-
将koa-onerror添加到Koa应用程序中:
const Koa = require('koa'); const app = new Koa(); // 添加koa-onerror中间件 onError(app);
-
可选:自定义错误处理器
const Koa = require('koa'); const app = new Koa(); // 添加koa-onerror中间件和自定义错误处理器 onError(app, { json: function (err, ctx) { ctx.status = 500; ctx.body = { message: err.message }; }, html: function (err, ctx) { ctx.status = 500; ctx.body = '<p>Something wrong, please contact administrator.</p>'; } });
以上是koa-onerror的基本用法,它会自动捕获应用程序中的所有错误,并将错误信息作为响应返回给客户端。如果需要自定义错误处理器,可以通过传递一个包含json和html两个属性的对象来实现。
二、使用koa-json-error 进行优化
这个中间件专门为纯 json 应用准备的
上面自定义的错误处理中间件, 无法处理 404 错误,并且实际工作场景不需要自己手动写, 社区中可以使用这些现成的
安装 koa-json-error并引用
npm i koa-json-error --save
const error = require('koa-json-error')
//使用 koa-json-error 的默认配置处理错误
//简单使用
app.use(error());
//高级使用
app.use(
error({
format: (err) => { // 返回错误的格式
return { code: err.status, message: err.message, result: err.stack }
},
postFormat: (err, obj) => { //根据不同环境,返回不同格式的错误信息
const { result, ...rest } = obj
return process.env.NODE_ENV == 'production' ? rest : obj
},
})
)
//修改配置使其在生产环境下禁用错误堆栈的返回
//因为生产环境返回那么多字段给客户有安全隐患,所以要修改配置
//比如让生产环境不返回 stack, 在开发环境返回:
//通常生产环境有个环境变量 production,
//所以检测该环境变量
app.use(error({
postFormat:(e, {stack, ...rest}) => process.env.NODE_ENV === 'production' ? rest : {stack, ...rest}
}));