深入了解koa原理
koa原理
⼀个基于nodejs的⼊⻔级http服务,类似下⾯代码:
1 2 3 4 5 6 7 8 9
| const http = require('http') const server = http.createServer((req, res) => { res.writeHead(200) res.end('hello world!') }) server.listen(3000,()=>{ console.log('server listen at 3000') })
|
koa的⽬标是⽤更简单化、流程化、模块化的⽅式实现回调部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| const http = require('http') class Koa { listen(...args){ const server = http.createServer((req,res)=>{ this.callback(req,res) }) server.listen(...args) } use(callback){ this.callback = callback } }
module.exports = Koa
const Koa = require('./koa') const app = new Koa()
app.use((req,res)=>{ res.writeHead(200) res.end('hello world!') }) app.listen(300,()=>{ console.log('server start at 3000') })
|
⽬前为⽌,Koa只是个⻢甲,要真正实现⽬标还需要引⼊上下⽂(context)和中间件机制
context
koa为了能够简化API,引⼊上下⽂context概念,将原始请求对象req和响应对象res封装并挂载到context上,并且在context上设置getter和setter,从⽽简化操作。
1 2 3 4
| app.use(ctx=>{ ctx.body = 'hehe' })
|
封装 context、request、response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| module.exports = { get url(){ return this.req.url }, get method(){ return this.req.method.toLowerCase() }, }
module.exports = { get body() { return this._body }, set body(val) { this._body = val } }
module.exports = { get url(){ return this.req.url }, get method(){ return this.req.method.toLowerCase() }, get body() { return this._body }, set body(val) { this._body = val } }
|
在koa.js中引入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| const http = require('http') const context = require('./context') const request = require('./request') const response = require('./response')
class Koa { listen(...args){ const server = http.createServer((req,res)=>{ const ctx = this.createContext(req,res) this.callback(ctx) res.end(ctx.body) }) server.listen(...args) } ... createContext(req,res){ const ctx = Object.create(context) ctx.request = Object.create(request) ctx.response = Object.create(response) ctx.req = ctx.request.req = req ctx.res = ctx.response.res = res return ctx } }
|
中间件
Koa中间件机制:Koa中间件机制就是函数式 组合概念Compose的概念,将⼀组需要顺序执⾏的函数复合为⼀个函数,外层函数的参数实际是内层函数的返回值。洋葱圈模型可以形象表示这种机制,是源码中的精髓和难点。
异步中间件:我们要⽀持async + await的中间件,要等异步结束后,再执⾏下⼀个中间件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function compose(middlewares){ return function(){ return dispatch(0) function dispatch(i){ let fn = middlewares[i] if(!fn){ return Promise.resolve() } return Promise.resolve( fn(function next(){ return dispatch(i+1) }) ) } } }
|
router
routes()的返回值是⼀个中间件,由于需要⽤到method,所以需要挂载method到ctx之上,修改request.js
实现方式请移步github—->write_koa