「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。
手撕koa,从零掌握koa的实现原理(4)
往期更文
前言
- 回顾昨天的内容,在我们
new Application的时候,分离了每个应用实例的上下文对象,使各个实例之间互不影响。 koa/koa/lib/application.jsconst http = require('http') const EventEmitter = require('events') const context = require('./context'); const request = require('./request'); const response = require('./response'); class Application extends EventEmitter { constructor(){ super() this.context = Object.create(context) this.request = Object.create(request) this.response = Object.create(response) } handleRequest = (req, res) => { res.statusCode = 200 res.setHeader('content-type','text/plain;charset=utf-8') res.end('自己实现的Koa') } listen(){ const server = http.createServer(this.handleRequest) server.listen(...arguments) } } module.exports = Application
我们在use中使用的ctx上下文对象是何时创建的?
-
我们先来看一段代码,开启一个
3000的端口,当我问访问localhost:3000/get的时候,会返回Hello World get,当我问访问localhost:3000/post的时候,会返回Hello World post,返回结果如下。const Koa = require('koa') const app = new Koa() app.use((ctx) => { if (ctx.path === '/get') { ctx.body = "Hello World get" }else if(ctx.path === '/post'){ ctx.body = "Hello World post" } }) app.listen(3000, () => { console.log('server start 3000') }) -
从上面的代码,我们可以想象到,肯定是在我们请求的时候,根据每次的请求不同来创建的
ctx对象,否则也不能根据每次的请求不同来做不同的响应。事实上koa中也是这么做的,在每次请求来临的时候,在handleRequest中再来创建此次请求的上下文对象,提供给用户使用。
handleRequest请求处理函数之创建每次请求的ctx上下文对象
handleRequest,是我们处理请求的函数,第一步我们需要完成的就是要创建每次的请求上下文对象ctx。我们把这个单独的功能抽离出来,在createContext方法中来处理。createContext分别做了以下事情。-
- 因为每次请求都是不同的,所以每一次请求都需要创建不同的
ctx对象,这和每个实例之间分离context是一样的思路。
- 因为每次请求都是不同的,所以每一次请求都需要创建不同的
-
- 把
ctx.request赋值为我们扩展的request请求对象,把原生的请求对象req分别给ctx.request.req和ctx.req同步一份。(至于为什么要这么做,我们后面会解释)
- 把
-
- 把
ctx.response赋值为我们扩展的response请求对象,把原生的请求对象req分别给ctx.response.res和ctx.res同步一份。(至于为什么要这么做,我们后面会解释)
- 把
koa/koa/lib/application.jsconst http = require('http') const EventEmitter = require('events') const context = require('./context'); const request = require('./request'); const response = require('./response'); class Application extends EventEmitter { constructor(){ super() this.context = Object.create(context) this.request = Object.create(request) this.response = Object.create(response) } createContext(req, res){ // req, res 是原生的 request 和 response 是我们自己扩展 //1. 每一次请求都需要创建不同的`ctx`对象 const ctx = Object.create(this.context) const request = Object.create(this.request) const response = Object.create(this.response) //2. 把`ctx.request`赋值为我们扩展的`request`请求对象, // 把原生的请求对象`req`分别给`ctx.request.req`和`ctx.req`同步一份。 ctx.request = request ctx.request.req = ctx.req = req //3. 把`ctx.response`赋值为我们扩展的`response`请求对象, // 把原生的请求对象`req`分别给`ctx.response.res`和`ctx.res`同步一份。 ctx.response = response; ctx.response.res = ctx.res = res; return ctx } handleRequest = (req, res) => { const ctx = this.createContext(req, res) } listen(){ const server = http.createServer(this.handleRequest) server.listen(...arguments) } } module.exports = Application
-
最后
看到这里的兄弟给点个赞吧,万分感谢。
今天是手写koa的第四天,主要还是为了更文的奖品,哈哈,加油,笔者也感觉每天在不停的巩固与学习中,收获很大。加油还有36天。