Would you like to clone this notebook?

When you clone a notebook you are able to make changes without affecting the original notebook.

Cancel

koa-compose 执行中间件

node v10.24.1
version: master
endpointsharetweet
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) { // 一个中间件里多次调用next if (i <= index) return Promise.reject(new Error('next() called multiple times')) index = i // fn就是当前的中间件 let fn = middleware[i] if (i === middleware.length) fn = next // 最后一个中间件如果也next时进入(一般最后一个中间件是直接操作ctx.body,并不需要next了) if (!fn) return Promise.resolve() // 没有中间件,直接返回成功 try { /* * 使用了bind函数返回新的函数,类似下面的代码 return Promise.resolve(fn(context, function next () { return dispatch(i + 1) })) */ // dispatch.bind(null, i + 1)就是中间件里的next参数,调用它就可以进入下一个中间件 // fn如果返回的是Promise对象,Promise.resolve直接把这个对象返回 // fn如果返回的是普通对象,Promise.resovle把它Promise化 return Promise.resolve(fn(context, dispatch.bind(null, i + 1))); } catch (err) { // 中间件是async的函数,报错不会走这里,直接在fnMiddleware的catch中捕获 // 捕获中间件是普通函数时的报错,Promise化,这样才能走到fnMiddleware的catch方法 return Promise.reject(err) } } } } const context = {}; const sleep = (time) => new Promise(resolve => setTimeout(resolve, time)); const test1 = async (context, next) => { console.log('1-start'); context.age = 11; await next(); console.log('1-end'); }; const test2 = async (context, next) => { console.log('2-start'); context.name = 'deepred'; await sleep(2000); console.log('2-end'); }; const fn = compose([test1, test2]); fn(context).then(() => { console.log('end'); console.log(context); });
Loading…

no comments

    sign in to comment