createContext(req, res)干了什么?

前言

最近在一次面试中被问到 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 属性增加增、读取、设置、改变一些方法,每个方法:

分析 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返回的内容:

  1. 我们发现context对象里面有app这个属性,并且request、response都有app、req、res

分析-3

request.ctx = response.ctx = context;
request.response = response;
response.request = request;
复制代码

从上面的图我们可以看出 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是什么了。

context关系

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值