Koa2源码阅读: ctx
2018-06-17 本文已影响0人
ceido
前言
koa 框架的目录结构如图:

在 koa/lib
文件夹下, 只有 4 个文件, 分别是 application.js
, context.js
, request.js
, response.js
.
而 application.js
是 koa 的入口文件, context.js
的作用是创建网络请求的上下文对象, request.js
是用于包装 koa 的 request 对象的, response.js则是用于包装 koa 的 response 对象的。
正文
下面就通过自己写一个小koa来理解它,我叫它为coa。
(1)先写个原生服务的:
server.js:
const http = require('http')
const server = http.createServer((req, res) => {
res.writeHead(200)
res.end('hello coa2')
})
server.listen(8000, () => {
console.log('server start')
})
(2)然后我们新建一个文件application.js
,进行简单的封装:
const http = require('http')
class Application {
constructor() {
this.callback = () => {}
}
use(callback) {
this.callback = callback
}
listen(...args) {
const server = http.createServer((req, res) => {
this.callback(req, res)
})
server.listen(...args)
}
}
module.exports = Application
这时候我们在server.js中就这样用了:
const Coa = require('./coa2')
const app = new Coa()
app.use((req, res) => {
res.writeHead(200)
res.end('hello coa2')
})
app.listen(8000, () => {
console.log('coa!')
})
(3)将req、res挂载到ctx
const http = require('http')
let request = {
get url() {
return this.req.url
}
}
let resopnse = {
get body() {
return this._body
},
set body(val) {
this._body = val
}
}
let context = {
get url() {
return this.request.url
},
get body() {
return this.resopnse.body
},
set body(val) {
this.resopnse.body = val
}
}
class Application {
constructor() {
this.context = context
this.request = request
this.resopnse = resopnse
}
use(callback) {
this.callback = callback
}
listen(...args) {
const server = http.createServer(async (req, res) => {
let ctx = this.createCtx(req, res)
await this.callback(ctx)
ctx.res.end(ctx.body)
})
server.listen(...args)
}
createCtx(req, res) {
let ctx = Object.create(this.context)
ctx.request = Object.create(this.request)
ctx.resopnse = Object.create(this.resopnse)
ctx.req = ctx.request.req = req
ctx.res = ctx.resopnse.res = res
return ctx
}
}
module.exports = Application
我们先创建request、resopnse、context。使用get、set是因为...因为源码是这么写的。哈,其实就是访问和设置时要做些额外的操作。
然后我们把request、resopnse、context挂到Application实例中,再通过调用createCtx把原生的req,res传入,整合一下后返回ctx。这样整合是为了以后便于扩展。
然后我们在server.js中的就可以这样写了:
const Coa = require('./coa2')
const app = new Coa()
app.use(async ctx => {
ctx.body = 'hello coa2 ' + ctx.url
})
app.listen(8000, () => {
console.log('coa!')
})
现在开始就有点像koa了有没有!