Koa入门和源码分析
1:koa入门 初始化文件 npm init 安装koa npm install koa –save (1)Hello world练习 const Koa = require("koa"); const app = new Koa(); //app是应用的起步 app.use(async(ctx,next) =>{ //ctx封装的是request 和 response ctx.body = "hello world" //next封装的是一下个中间件 }) app.listen(3000); 2:原理封装实现 (1) Hello world浅层原理实现 const http = require('http') const server = http.createServer((req,res)=>{ res.writeHead(200) res.end("hello world ") }) server.listen(8088) //封装use,listen方法 const Woa = require('./application') const app = new Woa() app.use((req,res)=>{ res.writeHead(200) res.end("hello server") }) app.listen(8088) 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 (2) context封装 构建ctx 挂载request和response对象 Ctx.body = xx 就可以修改相应 如何做到 Js的getter 和setter (3)同步的compose实现原理(中间件) function add(x,y){ return x+y } function double(z){ return z*2 } const res1 = add(1,2) const res2 = double(res1) console.log(res2) const res3 = double(add(1,2)) console.log(res3) const middlewares = [add, double] let len = middlewares.length function compose(midds){ return (...args)=>{ // 初始值 let res = midds[0](...args) for(let i=1;i<len;i++){ res = midds[i](res) } return res } } const fn = compose(middlewares) const res = fn(1,2) console.log(res) (3) 异步有序执行中间件(next实现原理递归) async function fn1(next){ console.log('fn1') await next() console.log('end fn1') } async function fn2(next){ console.log('fn2') await delay() await next() console.log('end fn2') } function fn3(next){ console.log('fn3') } function delay(){ return new Promise((reslove,reject)=>{ setTimeout(()=>{ reslove() },2000) }) } 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) })) } } } const middlewares = [fn1,fn2,fn3] const finalFn = compose(middlewares) finalFn() (4) 完整实现简单的koa const http = require('http') let request = { get url(){ return this.req.url } } let response = { get body(){ return this._body }, set body(val){ this._body = val } } let context = { get url(){ return this.request.url }, get body(){ return this.response.body }, set body(val){ this.response.body = val } } class Application { constructor(){ // this.callback = ()=>{} this.context = context this.request = request this.response = response this.middlewares = [] } use(callback){ this.middlewares.push(callback) // this.callback = callback } compose (middlewares){ return function(context){ return dispatch(0) function dispatch(i){ let fn = middlewares[i] if(!fn){ return Promise.resolve() } return Promise.resolve(fn(context,function next(){ return dispatch(i+1) })) } } } listen(...args){ const server = http.createServer(async(req,res)=>{ let ctx = this.createCtx(req,res) const fn = this.compose(this.middlewares) await fn(ctx) ctx.res.end(ctx.body) // this.callback(req,res) }) server.listen(...args) } createCtx(req, res){ let ctx = Object.create(this.context) ctx.request = Object.create(this.request) ctx.response = Object.create(this.response) ctx.req = ctx.request.req = req ctx.res = ctx.response.res = res return ctx } } module.exports = Application //server.js const Woa = require('./application') const app = new Woa() function delay(){ return new Promise((reslove,reject)=>{ setTimeout(()=>{ reslove() },2000) }) } app.use(async (ctx,next)=>{ ctx.body = '1' await next() ctx.body += '2' }) app.use(async (ctx,next)=>{ ctx.body += '3' await delay() await next() ctx.body += '4' }) app.use(async (ctx,next)=>{ ctx.body += '5' }) // app.use((req, res)=>{ // res.writeHead(200) // res.end('hello imooc') // }) app.listen(9092,()=>{ console.log('server runing on port 9092') })