如何从头实现一个node.js的koa框架

2020-06-17 06:09:13易采站长站整理

res.writeHead(200);
res.end('hello world');
});
app.listen(3000, () => {
console.log('listening on 3000');
});

可以看到,我们已经初步完成了对于http server的封装,主要实现了app.use注册回调函数,app.listen语法糖开启server并传入回调函数了,典型的koa风格。

但是美中不足的是,我们传入的回调函数,参数依然使用的是req和res,也就是node原生的request和response对象,这些原生对象和api提供的方法不够便捷,不符合一个框架需要提供的易用性。因此,我们需要进入第二条主线了。

主线二:构造request, response, context对象

如果阅读koa文档,会发现koa有三个重要的对象,分别是request, response, context。其中request是对node原生的request的封装,response是对node原生response对象的封装,context对象则是回调函数上下文对象,挂载了koa request和response对象。下面我们一一来说明。

首先要明确的是,对于koa的request和response对象,只是提供了对node原生request和response对象的一些方法的封装,明确了这一点,我们的思路是,使用js的getter和setter属性,基于node的对象req/res对象封装koa的request/response对象。

规划一下我们要封装哪些易用的方法。这里在文章中为了易懂,姑且只实现以下方法:

对于simpleKoa request对象,实现query读取方法,能够读取到url中的参数,返回一个对象。

对于simpleKoa response对象,实现status读写方法,分别是读取和设置http response的状态码,以及body方法,用于构造返回信息。

而simpleKoa context对象,则挂载了request和response对象,并对一些常用方法进行了代理。

首先创建request.js:


// request.js
let url = require('url');
module.exports = {
get query() {
return url.parse(this.req.url, true).query;
}
};

很简单,就是导出了一个对象,其中包含了一个query的读取方法,通过url.parse方法解析url中的参数,并以对象的形式返回。需要注意的是,代码中的this.req代表的是node的原生request对象,this.req.url就是node原生request中获取url的方法。稍后我们修改application.js的时候,会为koa的request对象挂载这个req。

然后创建response.js:


// response.js
module.exports = {
get body() {
return this._body;
},
/**
* 设置返回给客户端的body内容
*
* @param {mixed} data body内容
*/
set body(data) {
this._body = data;
},
get status() {
return this.res.statusCode;
},
/**
* 设置返回给客户端的stausCode
*
* @param {number} statusCode 状态码
*/
set status(statusCode) {
if (typeof statusCode !== 'number') {