准备工作
新建自己的 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.request return 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