Koa2核心原理

解析Koa2核心原理(手写KOA框架并解析)
前言:
相对于express框架,koa框架只是提供了async/await 的语法应用,大致上逻辑是相同的!
【Koa2核心原理】文章主要分为三个部分:

  1. koa2创建服务
  2. async/await 语法
  3. 自己写个koa2
一:koa2
使用koa2创建服务
/** * koa2 中间件原理 *1. app.use 先将注册的中间件收集起来 *2.实现next。上一个通过next实现触发执行下一个, * 等await后面的的函数执行完了在执行剩下的语句 */ const Koa = require('koa'); const app = new Koa(); // 注册中间件// logger app.use(async (ctx, next) => { await next(); console.log('第一个中间件 结束') }); app.use(async (ctx, next) => { await next(); console.log('第二个中间件 结束') }); // response app.use(async ctx => { ctx.body = 'Hello World'; console.log('第三个中间件 结束') }); //监听 app.listen(8000);

通过以上代码可以知道,我们先执行第一个中间件,遇到next呢,然后去执行第二个中间件,等后面的中间件都执行ok后,await解禁,执行第一个中间件的剩下的语句
二: async/await 语法
通常在异步的时候,我们都会使用Promise来,但是了多层的嵌套出现问题,那么如何让异步“同步化”?这里是使用 async/await的语法,当然,返回的是promise对象
/** * async timeout(){ *return "hello world" *throw new Error('rejected'); * } * * 其 也是函数,所以,直接调用,但是,返回的是promise对象 *timeout()=====>promise * * 如果有正确的返回值,那么就调用promise.solve(data) * 如果返回错误信息, promise.reject(data) * * 我们想要在里面执行异步函数读取数据, *await promise *为了防止错误,一般我们会try catch 包裹 */

三:自己写KOA2框架
const http = require('http'); class IKoa { constructor() { this.middlewareList = []; }/** * 收集 async中间件 */ use(fn){ this.middlewareList.push(fn) }//创建上下文,组合相关的请求来和去的数据 createContext(req,res){ const ctx ={ req, res } ctx.body = (data) => { let _d = data; if(typeof _d != 'string'){ _d = JSON.stringify(_d) } res.end(_d) } return ctx; }//组合中间件,定义next方法 compose(middlewareList){ return function(ctx){ // ctx.body({ //name:"a" // }) function next(i) { //取出一个中间件 const fn = middlewareList[i] if(fn){ //next.bind(null,i+1)= = next() 执行下一个中间件//这里也就是执行中间件函数dispatch相当于next fn(ctx, next.bind(null, i + 1))// promise } } //先执行第一个 return next(0) } } /** * 上下文 * @param{[type]}ctx * @param{Function} fn第一个中间件 * @returnfn 这里返回一个fn */ handleRequest(ctx,fn){ return fn(ctx) }callback(){ //获取第一个中间件 const fn = this.compose(this.middlewareList) return (req,res) => { const ctx = this.createContext(req,res); //这里返回第一个中间件,作为callback的返回 return this.handleRequest(ctx,fn) } }listen(...agrus){ //这里的核心,callback 返回是执行的第一个中间件,通过第一个中间件去next下一个中间件 const server = http.createServer(this.callback()); server.listen(...agrus) } } module.exports = IKoa

通过以上代码,可以看出,callback返回的是第一个中间件的函数的组装函数,在这个组装函数里面先执行自身,其参数是ctx上下文,和下一个中间件函数,其实next也就是下一个中间件函数,那么执行next就相当于执行下一个中间件,当然,返回的是Promise,那么就可以用await接收
测试使用:
const Koa = require('./i-koa'); const app = new Koa(); app.use( async (ctx, next) => { // ctx.body("111") next() console.log("111"); }) app.use( async (ctx, next) => { ctx.body("222")})app.listen(9000,()=>{ console.log("启动了"); })

    推荐阅读