koa源码由浅入深解析

koa源码解析

koa主要分成5个部分的概念,

  • Application
  • context
  • request
  • response
  • middleware

以上5个概念应该还是很好理解的

首先把koa给下载下来了,可以看到这里有四个文件,这里我主要讲下application,也就是最核心的一个模块

这里核心模块是application文件,从开始说起吧

const Emitter = require("events");
class Koa2 extends Emitter {
  constructor() {
    super();
    this.middleware = [];
    this.context = Object.create(context);
    this.request = Object.create(request);
    this.response = Object.create(response);
  }
  /**
   * 监听listen
   */
  listen(...args) {
    
  }
  /**
   * 回调函数
   */
  callback() {
    
  }
  /**
   * 使用插件
   * @param {} fn
   */
  use(fn) {
    
  }
}
复制代码

以上我们常用的是一些接口,从这些东西入手吧,这里继承了emitter这个构造函数,也就是node里面的事件监听,用过的人应该使用过下面这种

const app = new Koa2
app.on("error",()=>{

})
复制代码

看到这里大概就明白了为什么要继承emitter,主要是为了实现事件分发

第二步吧 use函数

这里很简单,其实就是把use中的函数加到中间件队列中,都应该能理解了

  /**
   * 使用插件
   * @param {} fn
   */
  use(fn) {
    this.middleware.push(fn);
    return this;
  }
复制代码

看到第三步 listen函数,将中间件的方法加入到callback中

这里相当于是一个语法糖

  /**
   * 监听listen
   */
  listen(...args) {
    let server = http.createServer(this.callback());
    server.listen(...args);
  }
    /**
   * 回调函数
   */
  callback() {
    const fn = conpose(this.middleware); //中间件的实现方式
    // if (!this.listenerCount('error')) this.on('error', this.onerror);
    const handleRequest = (req, res) => {
      const ctx = this.createContext(req, res);
      return this.handleRequest(ctx, fn);
    };
    return handleRequest;
  }
复制代码

这里将所有的中间件聚合成一个函数,这里聚合使用的是conpose,也就是koa的中间件洋葱模型

中间件 也就是koa的中间件洋葱模型,大家可以自己去查查

众所周知,koa是使用async的, 这里说的,这里的dispatch相当于next的意思吧!进入

module.exports = function(middleware) {
  return function(ctx, next) {
    // let index = -1;
    return dispatch(0);
    function dispatch(i) {
      let fn = middleware[i];
      if (i === middleware.length) {
        fn = next
      }
      if(!fn) {
        return Promise.resolve()
      }
      try {
        return Promise.resolve(fn(ctx, dispatch.bind(null, i + 1)));
      } catch (error) {
        return Promise.reject(error)
      }
    }
  };
};
复制代码

再回来看callback这个函数

  callback() {
    const fn = conpose(this.middleware); //中间件的实现方式
    // if (!this.listenerCount('error')) this.on('error', this.onerror);
    const handleRequest = (req, res) => {
      const ctx = this.createContext(req, res);
      return this.handleRequest(ctx, fn);
    };
    return handleRequest;
  }
  handleRequest(ctx, middleware) {
    return middleware(ctx).then(() => {
      console.log("中间件执行结束");
      // 这里可以拿到中间件里面修改的数据等
      /* 如ctx.response.body({

      }) */
      return ctx.response.res.end("hello");
    });
  }
  /**
   * 创建上下文
   */
  createContext(req, res) {
    // let ctx = {}
    const context = Object.create(this.context);
    context.request = Object.create(this.request);
    context.response = Object.create(this.response);
    context.app = this;
    context.response.res = res;
    context.request.req = req;
    return context;
  }
复制代码

reqres是http.createServer()的回调函数,这里就不多说了 下面的重点是创建一个上下文createContext

这里就链接到Object.create(this.context)等, 其实也就是将context,request,response实例化,将callback里面回传的request,response重写了一下,并且提供了一些方法 Object.create(this.request)Object.create(this.response) 就不细说了,都是封装一些方法,封装一些返回的值

进入到context文件,我们可以看到下面的这样一个函数调用,其实就是一个数据劫持

delegate(proto, 'response')
  .method('attachment')
  .method('redirect')
  .method('remove')
  .method('vary')
  .method('set')
  .method('append')
  .method('flushHeaders')
  .access('status')
  .access('message')
  .access('body')
  .access('length')
  .access('type')
  .access('lastModified')
  .access('etag')
  .getter('headerSent')
  .getter('writable');
复制代码

打个比方说ctx.body,其实就是ctx.response.body 这里做了一层代理,好处的话,可以不用污染ctx,并且不需要创建两份变量,这里可以去看看vue的data是怎么做的,为什么在this中能访问到data中的变量,这里是一样的

以上就是主要的koa内容了,至于其他都是开发中间件了 最后还有一个点 就是inspect,你看代码的时候会看到在生命对象和构造函数的时候都用到了这个inspect

举个例子哈!

const proto = {
  inspect(){
    return "hello inspect";
  }
}
if (util.inspect.custom) {
  proto[util.inspect.custom] = proto.inspect;
}
let a = Object.create(proto)

console.log(a)
// 输出 "hello inspect"
复制代码

koa里面用到,我理解的意思是,在打印的时候只打印出自己想打印出来的 ,别的不打印,其他就自己体会了。

转载于:https://juejin.im/post/5c24b01b6fb9a049a570f64f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值