Koajs中间件的定义(一)Koajs中间件的下篇(二)Koajs中间件的上下文(三)我们在第一篇文章中说过,“在Koa中,中间的A组件指的是一个独立的连接整个Koa应用并共享资源的插件”,注意两个词,“coherent”和“sharedresources”,与上面的代码一一对应,“coherent”对应“next”,“shared”资源对应上下文”。在Koa中,next贯穿整个应用。让我们分析一下接下来做什么。在中间件集合Koa类的构造函数中初始化了一堆数据,其中有两个很重要,一个是“中间件”,一个是“上下文”。(非关键代码使用...省略)constructor(){...this.middleware=[];this.context=Object.create(context);...}所有中间件都存储在一个数组中,当我们调用“app.use”方法时,我们会将我们自定义的中间件添加到数组中use(fn){...this.middleware.push(fn);returnthis;}最后通过"koa-compose"统一触发中间件队列callback(){constfn=compose(this.middleware);...return(req,res)=>{...fn(ctx).then(()=>respond(ctx)).抓住(ctx.onerror);};}koa-composekoa-compose源码只有几十行,关键代码不到10行。直接贴源码functioncompose(middleware){if(!Array.isArray(middleware))thrownewTypeError('Middlewarestackmustbeanarray!')for(constfnofmiddleware){if(typeoffn!=='function')thrownewTypeError('中间件必须由函数组成!')}/***@param{Object}context*@return{Promise}*@apipublic*/returnfunction(context,next){//最后调用的中间件#letindex=-1returndispatch(0)functiondispatch(i){if(i<=index)returnPromise.reject(newError('next()被多次调用'))index=iletfn=middleware[i]if(i===middleware.length)fn=nextif(!fn)returnPromise.resolve()try{returnPromise.resolve(fn(context,functionnext(){returndispatch(i+1)}))}catch(err){returnPromise.reject(err)}}}}如果我们需要使用Koa的洋葱模型可以直接调用koa-compose来达到目的constkoaCompose=require('koa-compose');constmiddleware1=(ctx,next)=>{console.log('middleware1>>>>>');下一个();console.log('middleware1<<<<<');}constmiddleware2=(ctx,next)=>{console.log('middleware2>>>>>');下一个();console.log('middleware2<<<<<');}constmiddleware3=(ctx,next)=>{console.log('middleware3>>>>>');控制台警告(ctx);下一个();console.log('middleware3<<<<<');}constfn=koaCompose([中间件1,中间件2,中间件3]);fn({a:'a'},(ctx)=>{console.warn(ctx);console.warn('上次下一次使用do=======<');returnctx;}).然后((ctx)=>{console.warn(ctx);console.warn('end=====<');});output:middleware1>>>>>middleware2>>>>>middleware3>>>>>{a:'a'}{a:'a'}最后下一个使用do=======
