当前位置: 首页 > Web前端 > HTML

一篇看懂洋葱圈模型的文章——那种看完就念念不忘的

时间:2023-04-02 21:07:17 HTML

洋葱圈。洋葱圈的概念起源于Koa。由于其灵活性和易扩展性,得到了广泛的应用。比如umi-request的洋葱中间件机制,阿里内部的eaas包(eggasaservice),都使用了洋葱圈的概念。关于洋葱圈,其实论坛里有很多源码阅读的文章,但是大多都是直接说源码,让人难以理解——包括我自己也经常这样,很难抓住核心概念;因此,本文将通过提问,制定计划,然后带着计划回头看源码来分析洋葱圈。希望大家读后能明白,读后不忘。1.不管你怎么说洋葱圈模型,这张图还是要出的。如您所见,每个中间件都是一个洋葱圈。每有一个请求进来,每个中间件都会执行两次。比如下面这个例子:constKoa=require("koa")constapp=newKoa()//middlewareAapp.use(async(ctx,next)=>{console.log("A1")awaitnext()console.log("A2")});//中间件Bapp.use(async(ctx,next)=>{console.log("B1")awaitnext()console.log("B2")});//中间件Capp.use(async(ctx,next)=>{console.log("C1")awaitnext()console.log("C2")});app.listen(3000);//输出//A1->B1->C1->C2->B2->A22。核心概念首先我们分析一下:每个中间件接收一个next参数,next函数运行前的中间件代码会在一开始执行,而next函数之后的代码会在所有内部中间件运行完毕后执行.我们需要怎么做才能达到上面洋葱圈的效果呢?首先,我们需要知道当前中间件的数组集合,然后构建一个组合方法,将这些中间件按照洋葱的结构进行组合并执行。有了这样的想法,我们再回头看看Koa是如何实现的:this.middleware是一个中间件集合的数组。使用koa-compose模块的compose方法完美构建执行顺序!接下来,我们只需要分别分析他们做了什么。//middleware用于保存中间件app.use=(fn)=>{this.middleware.push(fn)returnthis}//compose组合函数指定执行顺序functioncompose(middleware){//context:context,next:下一个要运行的传入函数returnfunction(context,next){functiondispatch(i){index=i//middlewareletfn=middleware[i]if(!fn)returnPromise.resolve()try{//假设和上面的例子一样,有A、B、C三个中间件//通过dispatch(0)发起第一个中间件A的执行//中间件A执行完毕后,next会执行为dispatch(1)//从而开始执行下一个中间件B,然后执行中间件C//所有中间件执行完一次后,执行Promise.resolve()//最内层中间件C的awaitnext()结束,并且会继续执行console.log("C2")//整个中间件C结束再次触发Promise.resolve//中间件B开始执行console.log("B2")//同理,中间件A执行console.log("A2")returnPromise.resolve(fn(context,()=>{returndispatch(i+1)}))}catch(err){returnPromise.reject(err)}}returndispatch(0)}}3.总体回顾Koa在中间件中采用了传入next参数的方式,并且然后结合中间件中间件数组和compose组合函数,构建洋葱圈的中间件执行结构,这就是洋葱圈中间件机制能够运行的原因。洋葱圈的代码并不复杂,但是这种提问的方式,带着解决方案看代码,希望能给大家一些启发。4.参考文章1.《浅析koa的洋葱模型实现》2.《Koa2 洋葱模型 —— compose 串联中间件的四种实现》3.《umi-request 网络请求之路》