koa源碼由淺入深解析

koa源碼解析

koa主要分紅5個部分的概念,

  • Application
  • context
  • request
  • response
  • middleware

以上5個概念應該仍是很好理解的vue

首先把koa給下載下來了,能夠看到這裏有四個文件,這裏我主要講下application,也就是最核心的一個模塊 node

這裏核心模塊是application文件,從開始提及吧app

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裏面的事件監聽,用過的人應該使用過下面這種koa

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

})
複製代碼

看到這裏大概就明白了爲何要繼承emitter,主要是爲了實現事件分發async

第二步吧 use函數

這裏很簡單,其實就是把use中的函數加到中間件隊列中,都應該能理解了函數

/** * 使用插件 * @param {} fn */
  use(fn) {
    this.middleware.push(fn);
    return this;
  }
複製代碼

看到第三步 listen函數,將中間件的方法加入到callback中

這裏至關因而一個語法糖ui

/** * 監聽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的中間件洋蔥模型this

中間件 也就是koa的中間件洋蔥模型,你們能夠本身去查查

衆所周知,koa是使用async的, 這裏說的,這裏的dispatch至關於next的意思吧!進入spa

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裏面用到,我理解的意思是,在打印的時候只打印出本身想打印出來的 ,別的不打印,其餘就本身體會了。

相關文章
相關標籤/搜索