use(fn) { if (typeof fn !== 'function') thrownewTypeError('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); returnthis; }
判断是不是一个'function',如果不是报错middleware must be a function!。
functioncompose (middleware) { if (!Array.isArray(middleware)) thrownewTypeError('Middleware stack must be an array!') for (const fn of middleware) { if (typeof fn !== 'function') thrownewTypeError('Middleware must be composed of functions!') }
returnfunction (context, next) { // last called middleware # let index = -1 returndispatch(0) functiondispatch (i) { if (i <= index) returnPromise.reject(newError('next() called multiple times')) index = i let fn = middleware[i] if (i === middleware.length) fn = next if (!fn) returnPromise.resolve() try { returnPromise.resolve(fn(context, dispatch.bind(null, i + 1))); } catch (err) { returnPromise.reject(err) } } } }
首先判断middleware是不是一个数组,不是数组抛出错误Middleware stack must be an array!。
逐个判断middleware里的元素是不是一个函数,不是的话,抛出错误Middleware must be composed of functions!。
返回一个函数
使用index巧妙的避免了next执行两次的问题。
if (i === middleware.length) fn = next,if (!fn) return Promise.resolve()这两行应该是递归终止条件。