<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          js 中的洋蔥模型

          共 4765字,需瀏覽 10分鐘

           ·

          2020-08-16 12:20

          來源:SegmentFault 思否

          作者:chenwl




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



          上面的圖片取自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)過compose處理打印出來的結(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       |            |           |        |          |            |                                 |            |           |+----------------------------------------------------------------------------------------------->        |          |            |                                 |            |           |        |          |            |                                 |            |           |        |          |            +---------------------------------+            |           |        |          +-----------------------------------------------------------+           |        +----------------------------------------------------------------------------------+

          那么我們就開始編寫compose函數(shù),首先它必須返回的是一個函數(shù),并且每次函數(shù)執(zhí)行,都需要將下一個函數(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ù)很不好理解,不過我們可以拆開它里面的函數(shù)來一步步分析:


          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)過reduce疊加,每次都將上一次的結(jié)果返回給下一個函數(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í)行      // 如果不存在下一個函數(shù)了,拿到傳參里面的函數(shù)執(zhí)行,這里需要保證傳參是一個函數(shù),對應(yīng)的是redux里面的dispatch參數(shù)      fn ? fn(next)() : cb()    }
          // 最終返回一個函數(shù) return ()=> dispatch(0);
          }};






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

          -?END -

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

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  九哥草逼网 | 精品人妻无码一区二区出白浆潮喷 | 免费毛片18女人毛片大全在线看 | 青娱乐免费视频在线 | 在线黄色小电影 |