准备工作
新建自己的 kaimo-koa 文件夹,结构如下:
- lib
application.js
:创建应用context.js
:上下文request.js
:koa 中自己实现的 request 的对象response.js
:koa 中自己实现的 response 的对象
package.json
:里面需要注意 main 字段,我们需要将lib/application.js
作为入口
{"name": "kaimo-koa","version": "1.0.0","description": "","main": "lib/application.js","directories": {"lib": "lib"},"scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC"
}
ctx 是什么东西?
ctx 中整合了 request 和 response,req 以及 res
- koa 自己实现的 request 和 response
- http 原生的 req 以及 res
ctx.request.req.url
跟 ctx.req.url
是等价的
ctx.path
就是去 ctx.request.path
上取的,ctx.request
内部使用了 url 模块进行解析
代码实现基本的逻辑以及属性的扩展
application.js
:创建应用
const EventEmitter = require("events");
const http = require("http");
const context = require("./context");
const request = require("./request");
const response = require("./response");console.log("kaimo-koa---->");class Application extends EventEmitter {constructor() {super();// 防止多个实例共享 context request response 需要进行拷贝this.context = Object.create(context);this.request = Object.create(request);this.response = Object.create(response);}use(callback) {this.callback = callback;}// 创建一个上下文createContext(req, res) {// 每次请求都应该是一个全新的 context,需要拷贝let ctx = Object.create(this.context);// 上下文中有一个 request 对象,是自己封装的ctx.request = Object.create(this.request);// 上下文中还有一个 req 属性 指代的是原生的 req,自己封装的 request 对象上有 req 属性ctx.req = ctx.request.req = req;return ctx;}handleRequest(req, res) {const ctx = this.createContext(req, res);this.callback(ctx);}listen(...args) {const server = http.createServer(this.handleRequest.bind(this));server.listen(...args);}
}module.exports = Application;
request.js
:koa 中自己实现的 request 的对象,进行属性扩展
const url = require("url");
const request = {// 属性访问器的方式 ctx.request.url 就会执行 url()get url() {// this 就是 ctx.requestreturn this.req.url;},get path() {return url.parse(this.req.url).pathname;},get query() {return url.parse(this.req.url).query;}// ... 可以自己添加其他的扩展属性
};module.exports = request;
编写 demo.js
测试
const Koa = require("./kaimo-koa");
const app = new Koa();app.use(async (ctx, next) => {ctx.body = "Hello kaimo Koa";console.log("url---->", ctx.request.url);console.log("path---->", ctx.request.path);console.log("query---->", ctx.request.query);
});app.on("error", (err) => {console.log(err);
});app.listen(3000);
启动服务后访问 http://localhost:3000/kaimo?a=313
nodemon demo.js