美文网首页
createContext(req, res)

createContext(req, res)

作者: 原型设计 | 来源:发表于2019-03-24 00:57 被阅读0次

    前言

    最近在一次面试中被问到 koa 里面的 delegates、request、respone、req、res之间的关系?我当时只回答了 koa-compose递归原理,虽然最后通过了面试,但是我觉得还是有必要追其原因,因为我没回答出来。

    Koa 源码 createContext(req,res)

     createContext(req, res) {
        const context = Object.create(this.context);
        const request = context.request = Object.create(this.request);
        const response = context.response = Object.create(this.response);
        context.app = request.app = response.app = this;
        context.req = request.req = response.req = req;
        context.res = request.res = response.res = res;
        request.ctx = response.ctx = context;
        request.response = response;
        response.request = request;
        context.originalUrl = request.originalUrl = req.url;
        context.state = {};
        return context;
      }
    
    

    前提

    首先我们必须先了解一下代码

    this.context = Object.create(context);
    this.request = Object.create(request);
    this.response = Object.create(response);
    

    分析 context

    1. context

      const context = require('./context');
      this.context = Object.create(context);
      

      1.1. context 干了什么?

      const delegate = require('delegates');
      const proto = module.exports = {
          ...
      }
      
      delegate(proto, 'response')
        .method('attachment')
        .method('redirect')..
      
      delegate(proto, 'request')
        .method('acceptsLanguages')
        .method('acceptsEncodings')...
      
      

      1.2. delegates干了什么?

      module.exports = Delegator;
      
      function Delegator(proto, target) {} 
      
      Delegator.auto = function(proto, targetProto, targetProp){}
      
      Delegator.prototype.method = function(name){
          proto[name] = function(){
              return this[target][name].apply(this[target], arguments);
          };
          
          return this;
      }
      
      Delegator.prototype.access = function(name){
          return this.getter(name).setter(name);
      };
      
      Delegator.prototype.getter = function(name){
          proto.__defineGetter__(name, function(){
              return this[target][name];
          });
          return this;
      }
      
      Delegator.prototype.setter = function(name){
       
        proto.__defineSetter__(name, function(val){
          return this[target][name] = val;
        });
      
        return this;
      };
      

      常用的 method 方法内部实现:

       proto[name] = function(){
          return this[target][name].apply(this[target], arguments);
       };
      

      其实就是给context.js 返回的对象proto 对于request 、response 属性增加增、读取、设置、改变一些方法,每个方法:

    2. request.js 和 response.js

      module.exports  ={
          ...
      }
      request.js 封装了req ,response.js封装了res
      
      

    分析-1:

    const context = Object.create(this.context);
    const request = context.request = Object.create(this.request);
    const response = context.response = Object.create(this.response);
    

    先创建context对象、然后为context上下文增加request、request属性。现在context除了context.js文件导出的proto对象的方法和属性外、以及利用delegates在proto.request、proto.response上面定义的方法外,现在又在context.request、context.respons上面增加了分别对应request.js 和 response.js 默认导出的方法,request.js 又封装了req ,response.js封装了res。

    分析-2:

    context.app = request.app = response.app = this;
    context.req = request.req = response.req = req;
    context.res = request.res = response.res = res;
    
    1. 整个context返回的内容:
    image
    1. 我们发现context对象里面有app这个属性,并且request、response都有app、req、res
    image

    分析-3

    request.ctx = response.ctx = context;
    request.response = response;
    response.request = request;
    
    image

    从上面的图我们可以看出 context.request.ctx response 、context.response.ctx request 都有对应的属性

    分析-4

    context.originalUrl = request.originalUrl = req.url;
    context.state = {};
    
    

    在context上下文中我们可以查看originalUrl、state

    总结:

    
    const Koa = require("koa");
    
    const app = new Koa();
    
    app.use(async ctx => {
      ctx.body = 'Hello World';
    });
    
    app.listen(3000);
    
    

    在koa 源码createContext函数里面console.log(context) 就可以看出整个函数返回context是什么了。

    createContext 返回了什么?(context)

    image

    相关文章

      网友评论

          本文标题:createContext(req, res)

          本文链接:https://www.haomeiwen.com/subject/avkyvqtx.html