koa source code reading application.js

constructor

Role: Initialization


  /**
    *
    * @param {object} [options] Application options
    * @param {string} [options.env='development'] Environment
    * @param {string[]} [options.keys] Signed cookie keys
    * @param {boolean} [options.proxy] Trust proxy headers
    * @param {number} [options.subdomainOffset] Subdomain offset
    * @param {boolean} [options.proxyIpHeader] proxy ip header, default to X-Forwarded-For
    * @param {boolean} [options.maxIpsCount] max ips read from proxy ip header, default to 0 (means infinity)
    *
    */

  constructor(options) {
    
    
    super();
    //这个就是new Koa(options)中的options
    options = options || {
    
    };
    //把options参数复制到实例上
    this.proxy = options.proxy || false;
    this.subdomainOffset = options.subdomainOffset || 2;
    this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For';
    this.maxIpsCount = options.maxIpsCount || 0;
    this.env = options.env || process.env.NODE_ENV || 'development';
    if (options.keys) this.keys = options.keys;
    //:point_down:中间件队列
    this.middleware = [];
    //:point_down:复制一份到自己身上
    this.context = Object.create(context); // const context = require('./context');
    this.request = Object.create(request); // const request = require('./request');
    this.response = Object.create(response);// const response = require('./response');
    // util.inspect.custom support for node 6+
    /* istanbul ignore else */
    if (util.inspect.custom) {
    
    
      this[util.inspect.custom] = this.inspect;
    }
  }

listen

Role: start the server listening port

  /**
   * Shorthand for:
   *
   *    http.createServer(app.callback()).listen(...)
   *
   * @param {Mixed} ...
   * @return {Server}
   * @api public
   */

  listen(...args) {
    
    
    debug('listen');
    //node的创建一个服务器 
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }

The point of understanding this code isthis.callback

callback

  /**
   * Return a request handler callback
   * for node's native http server.
   *
   * @return {Function}
   * @api public
   */

  callback() {
    
    
    //这一步处理中间件 最后返回一个promise
    const fn = compose(this.middleware);

    if (!this.listenerCount('error')) this.on('error', this.onerror);
    
    // 因为callback返回handleRequest 所以这里的req,res实际上http.createServer的回调函数的参数
    const handleRequest = (req, res) => {
    
     
      //创建上下文 就是把req res request response app 组合在一起 具体的在context.js源码阅读中
      const ctx = this.createContext(req, res);
      //ctx 是上下文 fn是上面执行之后返回的Promise
      return this.handleRequest(ctx, fn);
    };
    //返回的就是上面定义的函数
    return handleRequest;
  }

compose

This function returns a promise
function: the methods in the middleware array are executed in turn to pass the context context, but the next time the opportunity is executed is to actively trigger next, which is actually dispatch.bind(null, i + 1)this function

/**
 * Compose `middleware` returning
 * a fully valid middleware comprised
 * of all those which are passed.
 *
 * @param {Array} middleware
 * @return {Function}
 * @api public
 */

function compose (middleware) {
    
    
  if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
  for (const fn of middleware) {
    
    
    if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
  }

  /**
   * @param {Object} context
   * @return {Promise}
   * @api public
   */

  return function (context, next) {
    
    
    // last called middleware #
    let index = -1
    return dispatch(0)
    function dispatch (i) {
    
    
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      index = i
      let fn = middleware[i]
      if (i === middleware.length) fn = next
      if (!fn) return Promise.resolve()
      try {
    
    
        return Promise.resolve(fn(context, dispatch.bind(null, i + 1))); //这里是关键点
      } catch (err) {
    
    
        return Promise.reject(err)
      }
    }
  }
}

this.handleRequest

Role: Wait for the completion of the middleware execution, and then process the response, handle the error

  handleRequest(ctx, fnMiddleware) {
    
    
    const res = ctx.res;
    res.statusCode = 404; //:point_right:先预设一个404
    const onerror = err => ctx.onerror(err); 
    const handleResponse = () => respond(ctx);//:point_down: 响应处理帮助函数
    onFinished(res, onerror); //http请求结束或者完成或者出错时 执行回调函数 -->这里应该是错误处理?
    return fnMiddleware(ctx).then(handleResponse).catch(onerror);
  }

use

Role: middleware use function, push fn into the array and check if it is a generator function by the way, v3 will no longer support

  use(fn) {
    
    
    if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
    if (isGeneratorFunction(fn)) {
    
    
      deprecate('Support for generators will be removed in v3. ' +
                'See the documentation for examples of how to convert old middleware ' +
                'https://github.com/koajs/koa/blob/master/docs/migration.md');
      fn = convert(fn);
    }
    debug('use %s', fn._name || fn.name || '-');
    this.middleware.push(fn);
    return this;
  }

Guess you like

Origin blog.csdn.net/weixin_38616850/article/details/108987086