1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        js 中的洋蔥模型

        共 4765字,需瀏覽 10分鐘

         ·

        2020-08-16 12:20

        來(lái)源:SegmentFault 思否

        作者:chenwl




        這篇文章探討js的洋蔥模型以它的實(shí)現(xiàn)原理,洋蔥模型顧名思義,指的是方法的執(zhí)行像洋蔥一樣,一層一層往里執(zhí)行,直到中心點(diǎn)后,再一層一層往外出來(lái)。



        上面的圖片取自koa中間件的流程控制圖,react-redux的中間件也采用了一樣的原理。


        let fn1 = (next) => {  console.log(1)  next()  console.log(2)}
        let fn2 = (next) => { console.log(3) next() console.log(4)}
        let fn3 = (next) => { console.log(5) next() console.log(6)}
        const middlewares = [fn1, fn2, fn3];
        compose(middlewares)();/* result:135642*/


        合并后的middlewares數(shù)組,經(jīng)過(guò)compose處理打印出來(lái)的結(jié)果是:1、3、5、6、4、2,我們可以想到compose函數(shù)回的函數(shù)里面是怎么執(zhí)行的:


                +----------------------------------------------------------------------------------+        |                                                                                  |        |                              fn1                                                 |        |                                                                                  |        |          +-----------------------------------------------------------+           |        |          |                                                           |           |        |          |                    fn2                                    |           |        |          |                                                           |           |        |          |            +---------------------------------+            |           |        |          |            |                                 |            |           |        | action   |  action    |        fn3                      |    action  |   action  |        | 1        |    3       |                                 |      4     |     2     |        |          |            |   action              action    |            |           |        |          |            |     5                   6       |            |           |        |          |            |                                 |            |           |+----------------------------------------------------------------------------------------------->        |          |            |                                 |            |           |        |          |            |                                 |            |           |        |          |            +---------------------------------+            |           |        |          +-----------------------------------------------------------+           |        +----------------------------------------------------------------------------------+

        那么我們就開(kāi)始編寫(xiě)compose函數(shù),首先它必須返回的是一個(gè)函數(shù),并且每次函數(shù)執(zhí)行,都需要將下一個(gè)函數(shù)作為參數(shù)傳給它,這樣才能夠讓方法一層層的執(zhí)行下去,直到最里面一層:


        function compose(middlewarw) {  return function(args){    dispatch(0);    function dispatch(index){      let fn = middlewarw[index] || args;      if(typeof fn !== "function") return;      let next = ()=> dispatch(index+1);      fn(next);    }  }};


        當(dāng)然我們也希望碰上異步函數(shù),也能正常的執(zhí)行:

        function asyncFn() {  return new Promise((resolve, reject) => {    setTimeout(() => {      console.log("delay...");      resolve();    }, 1000);  });}
        let fn1 = async (next) => { console.log(1) await next() console.log(2)}
        let fn2 = async (next) => { console.log(3) await asyncFn(); await next() console.log(4)}
        let fn3 = async (next) => { console.log(5) await next() console.log(6)};
        function compose(middlewarw) { return function (args) { dispatch(0); function dispatch(index) { let fn = middlewarw[index] || args; if (typeof fn !== "function") return Promise.resolve(); let next = () => dispatch(index + 1);
        // 給執(zhí)行函數(shù)添加返回成功的Promise.resolve return Promise.resolve(fn(next)) } }};
        compose([fn1,fn2,fn3])();


        react-redux 的中間件實(shí)現(xiàn)


        react-redux的中間件是這樣實(shí)現(xiàn)compose函數(shù)的:


        function compose(middlewarw) {  return middlewarw.reduce((total, next) => (...args) => total(next(...args)));}


        react-redux中間件執(zhí)行的函數(shù)很不好理解,不過(guò)我們可以拆開(kāi)它里面的函數(shù)來(lái)一步步分析:


        let fn1 = (next) => {  return ()=>{    console.log(1)    next()    console.log(2)  }}
        let fn2 = (next) => { return ()=>{ console.log(3) next() console.log(4) }}
        let fn3 = (next) => { return ()=>{ console.log(5) next() console.log(6) }}
        let dispatch = compose([fn1,fn2,fn3])(()=> console.log("dispatch"));
        dispatch();


        middlewarw經(jīng)過(guò)reduce疊加,每次都將上一次的結(jié)果返回給下一個(gè)函數(shù)作參數(shù):


        // 第1次 reduce 的返回值,變成 total 傳遞到下一次arg => fn1(() => fn2(arg));
        // 第2次 reduce 的返回值,繼續(xù)作為下一次的 totalarg => (arg => fn1(() => fn2(arg)))(() => fn3(arg));


        或者將compose轉(zhuǎn)成比較好理解的函數(shù)迭代形式:


        function compose(middlewarw) {  return function(cb) {    function dispatch(index){      let fn = middlewarw[index];      let next = ()=>dispatch(index+1); // 下一次的函數(shù)執(zhí)行      // 如果不存在下一個(gè)函數(shù)了,拿到傳參里面的函數(shù)執(zhí)行,這里需要保證傳參是一個(gè)函數(shù),對(duì)應(yīng)的是redux里面的dispatch參數(shù)      fn ? fn(next)() : cb()    }
        // 最終返回一個(gè)函數(shù) return ()=> dispatch(0);
        }};






        點(diǎn)擊左下角閱讀原文,到?SegmentFault 思否社區(qū)?和文章作者展開(kāi)更多互動(dòng)和交流。

        -?END -

        瀏覽 59
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            freehd国产hd | 高清无码视频在线观看免费 | 五月丁香婷婷激情网 | 在线免费黄色视频网站 | 熟女自拍偷拍 | 欧美性猛交 乱大交极品 | 久久久精品视频在线观看 | 亚洲无码四区 | 中文字幕精品一区二区三区精品 | 国产婷婷内射 |