关于koa 异常处理这块 - CNode技术社区

关于koa 异常处理这块
发布于 6 年前 作者 chenye2017 5127 次浏览 来自 问答
const Koa = require('koa');
const Router = require('koa-router');
let app = new Koa;
let router = new Router();
const auth = async (ctx, next) => {
 // let error = new Error('this is an error')
 ctx.throw(500)
 await next(error)
}
router.get('/:user', auth, (ctx) => {
 let user = ctx.params.user;
 let name = ctx.params.name;
 console.log(error)
 ctx.response.type = 'json';
 ctx.body = {
 user,
 name
 }
})
 app.use(async ( ctx, next) => {
 try {
 await next()
 } catch (err) {
 
 ctx.type = 'json'
 ctx.body = {
 message : err.message
 } 
 ctx.app.emit('error', err, ctx);
 }
})
app.use(router.routes())
app.on('error', (err,ctx) => {
 console.log(111)
 ctx.type = 'json'
 ctx.body = {
 message : err.message
 }
})
app.listen(8092, () => {
 console.log('8092 is listening koa');
})

当我没有加中间件异常处理函数的时候, koa 的on error 事件能触发,但是ctx.type json 不能生效,不知道是什么原因,加上异常处理中间件后,on error 事件中的ctx.type 能生效,有木有大手子能解释一下

2 回复

其实我不建议在router层做这个事情,可以新建一个controller层通过工厂生产出controller器的入口做代理,拦截proxy。否则路由不够直观后面跟着一大长条方法,第二自定义空间有限导致每个方法都要做类似的事情。

下面是针对问题的回答:

这么和你说吧,在发生处理http请求的时候,在中间件发生错误的时候会调用 ctx的onerror方法,而不是只调用了app的on(error,...)方法

// /lib/application.js
handleRequest(ctx, fnMiddleware) {
 const res = ctx.res;
 res.statusCode = 404;
 const onerror = err => ctx.onerror(err);
 const handleResponse = () => respond(ctx);
 onFinished(res, onerror);
 return fnMiddleware(ctx).then(handleResponse).catch(onerror);
 }

但是ctx的onerror方法,不仅仅会调用app的on(error,...)方法,还会覆盖你的ctx.type,如下

// /lib/context.js
 onerror(err) {
 	// 省略代码...
	// 如果异常之前就被拦截,这里的err就是null,就不会往下走了
 if (null == err) return;
 if (!(err instanceof Error)) err = new Error(util.format('non-error thrown: %j', err));
	// 省略代码...
	// 在这里调用了你的on(error)
 this.app.emit('error', err, this);
	// 省略代码...
	// 关键在这里强制设置了ctx.type把你的覆盖了
 this.type = 'text';
	// 省略代码...
	// 发送数据请求结束
 res.end(msg);
 },

为什么呢?区别就是你使用了处理异常中间件相当于手动只调用了app的on(error,...)方法。而没使用在处理异常中间件的时候就抛错走了ctx的的onerror方法,这个方法不仅仅会调用app的on(error,...)方法,还会覆盖你的ctx.type

不应该调用 ctx.onError,而是应该直接 ctx.throw

回到顶部

AltStyle によって変換されたページ (->オリジナル) /