koa-application继承自events模块,具有发布-订阅功能
1 events模块需要处理error错误
2 Koa错误处理
3 源码分析
3.1 错误处理
对应events模块错误处理,至少存在一个error处理函数来兜底,防止node进程挂掉
// applicationcallback() {if (!this.listenerCount('error')) this.on('error', this.onerror);}// Default error handleronerror(err) {if (!(err instanceof Error)) throw new TypeError(util.format('non-error thrown: %j', err));if (404 == err.status || err.expose) return;if (this.silent) return;const msg = err.stack || err.toString();console.error();console.error(msg.replace(/^/gm, ' '));console.error();}};
同时可以自定义错误处理程序,参考2中,集中日志处理,可以多次订阅error事件,来处理自己业务错误的处理程序。
app.on('error', err => {// 错误处理1});app.on('error', err => {// 错误处理1});app.on('error', err => {// 错误处理3});
3.2 错误触发
在处理请求过程中,如果出错,就会进入promise实例的catch方法,在这个方法里调用context原型上的ctx.onerror方法
// applicationhandleRequest(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里面触发调用application实例emit方法,触发error事件,同时传参(err,ctx),对应2中,出现错误,无发响应,仍然传递当前请求上下文context实例。
// context.jsonerror(err) {// 前置处理// delegatethis.app.emit('error', err, this);// 后置处理}
fnMiddleware 是koa-compose处理app.middleware后的函数,返回promise实例
// koa-composefunction compose (middleware) {if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')for (const fn of middleware) {if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')}/*** @param {Object} context* @return {Promise}* @api public*/return function (context, next) {// last called middleware #let index = -1return dispatch(0)function dispatch (i) {debuggerif (i <= index) return Promise.reject(new Error('next() called multiple times'))index = ilet fn = middleware[i]if (i === middleware.length) fn = nextif (!fn) return Promise.resolve()try {return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));} catch (err) {return Promise.reject(err)}}}}
