koa 2.0 中间件部分代码注释

2017-11-01  本文已影响0人  嘿__老刘
'use strict'

/**
 * Expose compositor.
 */

module.exports = compose

/**
 * 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
   */
  //context 与 next 由http.createServer 为其传入  返回的匿名函数为传入到createserver中
  return function (context, next) {
    // last called middleware #
    let index = -1
    return dispatch(0)
    function dispatch (i) {
      //index =》 计数器
      //i     =》 中间件数组的索引
      //保证不会执行到undefined
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      //更改计数器的值
      index = i
      //将middleware的i元素赋值给 fn
      // 我感觉是1、为了以后写着方便
      // 2、 middleware[i]每次都会执行数组查找元素的操作
      // fn应该拿到的是地址
      let fn = middleware[i]
      // 如果没有函数了,则直接执行next结束中间件调用链
      if (i === middleware.length) fn = next
      //如果fn不存在则直接空函数
      if (!fn) return Promise.resolve()
      //用try catch 包裹 防止异常情况阻塞服务运行
      //为什么只在此处用try catch包裹
      //1、try catch 过多会影响代码的运行效率
      //2、前半部分代码,基本上不会出现不可预料的错误,并且异常处理已做
      //3、此处运行外部嵌入的函数,不可预知是否会出现异常未被处理的情况
      try {
        //返回
        //此处解释了为什么在中间件代码中 await next 会将执行权限交给下一个中间件
        //1、此处的function next 也就是中间件中的next
        //2、 await next 也就是等待此处dispatch执行完毕,也就是将执行权限交给下一个中间件
        return Promise.resolve(fn(context, function next () {
          return dispatch(i + 1)
        }))
      } catch (err) {
        //返回错误promise
        return Promise.reject(err)
      }
    }
  }
}
上一篇下一篇

猜你喜欢

热点阅读