可以看到,onerror方法的对异常的处理主要是获取异常状态码,当err.code为'ENOENT'的时候,返回的消息头设置为404,否则默认设置为500,然后消息体设置为err.message,如果异常中message属性为空,则默认消息体设置为'Internal error'。此后调用ctx.res.end返回消息,这样就能保证即使异常情况下,客户端也能收到返回值。最后通过this.emit出发error事件。
然后我们写一个example来验证错误处理:
let simpleKoa = require('./application'); let app = new simpleKoa(); app.use(async ctx => { throw new Error('ooops'); }); app.on('error', (err) => { console.log(err.stack); }); app.listen(3000, () => { console.log('listening on 3000'); });
浏览器访问'localhost:3000'的时候,得到返回'ooops',同时http状态码为500 。同时app.on('error')订阅到了异常事件,在回调函数中打印出了错误栈信息。
关于错误处理,这里多说一点。虽然koa中内置了错误处理机制,但是实际业务开发中,我们往往希望能够自定义错误处理方式,这个时候,比较好的办法是在最开头增加一个错误捕获中间件,然后根据错误进行定制化的处理,比如:
// 错误处理中间件 app.use(async (ctx, next) => { try { await next(); } catch (err) { // 在这里进行定制化的错误处理 } }); // ...其他中间件
至此,我们就完整实现了一个轻量版的koa框架。
结语
完整的simpleKoa代码库地址为:simpleKoa,里面还附带了一些example。
理解了这个轻量版koa的实现原理,读者还可以去看看koa的源码,会发现机制和我们实现的框架是非常类似的,无非是多了一些细节,比如说,完整koa的context/request/response方法上面挂载了更多好用的method,或者很多方法中容错处理更好等等。具体在本文中就不展开讲了,留给感兴趣的读者去探索吧~。