<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 什么是Redux中間件 ![](https://box.kancloud.cn/6758d11e210483c91115d0f9cd74f62a_800x600.png) 中間件是插入在用戶發射`action`動作之后到`reducer`接收到這個動作之前這個時機的處理器,它能完成一些額外的邏輯。 ## 存在中間件時倉庫的初始化 平時我們是這么初始化一個有中間件的倉庫的 ``` import {createStore,applyMiddleware} from 'redux'; let store = createStore(reducer,{astate:..,bstate:...,...},applyMiddleware(xx,yy,zz)); ``` 其實內部是這樣調用的 ``` let store = applyMiddleware(xxx,yyy,...)(createStore)(reducer,{astate:..,bstate:...,...}) ``` emmm,原理是這樣的 ``` export default function createStore(reducer, preloadedState, enhancer){ // 增強器 if(enhancer && typeof enhancer === 'function'){ return enhancer(createStore)(reducer,preloadedState) } ... ``` So,我們現在知道了,如果有中間件,會先執行`applyMiddleware`應用中間件這個方法,并且將`createStore`、`reducer`、`preloadedState`傳到applyMiddleware這個方法里面,在里面初始化倉庫。 ## 創建一個中間件 我們再來看看平時我們是怎么定義一個中間件的 ``` let logger = ({dispatch,getState})=>next=>action=>{ //do shome thing else console.log(1); next(action); console.log(11); //do some thing else agin } ``` 它等價于 ``` let logger = function({dispatch,getState}){ return function(next){ return function(action){ //do shome thing else console.log(1); next(action); console.log(11); //do some thing else agin } } } ``` 其中,`getState` 就是`createStore`初始化一個倉庫時原本導出的getState,`action`也還是用戶所發射的那個reducer所接受的那個action, 但`dispatch`不再是createStore所導出的那個了,而是經過中間件包裝后的dispatch。 另外`next`其實是另外一個中間件,和Koa中的中間件一樣我們需要手動調用next來讓隊列中的中間件一次執行。并且中間件的運行及結果依然遵循**洋蔥模型**。 我們來看這樣一個栗子,假若我們有兩個中間件 ``` //中間件1 let middle1 = function({dispatch,getState}){ return function(next){ return function(action){ //do shome thing else console.log(1); next(action); console.log(11); //do some thing else agin } } } //中間件2 let middle2 = function({dispatch,getState}){ return function(next){ return function(action){ //do shome thing else console.log(2); next(action); console.log(22); //do some thing else agin } } } ``` 然后我們這樣初始化倉庫時這樣注冊他們 ``` let store = applyMiddleware(middle2,middle1)(createStore)(reducer); ``` 那么當我們發射一個動作時,比如說 ``` <button onClick={this.props.increment}>+</button> ``` 那么此時就會調用派發,只不過此時的派發方法是經過先經過`middle1`包裝后又經過`middle2`包裝的方法。它會先執行`middler2`額外添加的一部分代碼,然后再執行`middle1`額外添加的一部分代碼,然后才會真正的派發,派發完以后又會將`middle1`剩下的代碼執行完,最后是`middle2`剩下的代碼。 ![](https://box.kancloud.cn/e80cafbb47fa5a1adc36000b21505138_471x327.png) 執行結果會是:先輸出1,再輸出2,再執行store.dispatch,再輸出22,最后輸出11 接下來,我們來看這樣的模型具體是怎樣實現的。 ## applyMiddleware.js 這個方法最后會將原本的`store.dispatch`給替換成**新的dispatch**,這個新的dispatch是則是我們上面所說的經過中間件層層包裝后的新的dispatch。 ``` //applyMiddleware.js export default function(...middlewares){ return function(createStore){ return function(reducer,preloadedState){ let store = createStore(reducer,preloadedState); let dispatch; let middlewareAPI = { getState:store.getState ,dispatch:action=>dispatch(action) } middlewares = middlewares.map(middleware(middlewareAPI)); dispatch = compose(...middlewares)(store.dispatch); return {...store,dispatch}; } } } ``` ## compose.js 在`applyMiddleware.js`中我們用到了一個`compose`方法, 這個方法會把中間件串行起來,并且一層包一層,按照`applyMiddleware()`調用時中間件注冊的順序,**先注冊的會成為洋蔥模型最外面的一層**,后注冊的則往里一層,最里面是原本的store.dispatch。 ``` //compose.js export default function(...fns){ return function(...args){ let last = fns.pop(); return fns.reduceRight((val,fn)=>{ return fn(val); },last(...args)); } } //--- --- --- //高逼格版 export default function(...fns){ if(fns.length === 1)return fns[0]; return fns.reduce((a,b)=>(...args)=>a(b(...args))); } ``` 為了便于理解`compose`函數的作用,請看一下以下的例子 ``` function add1(str){ return str+'com'; } function add2(str){ return str+'po'; } function add3(str){ return str+'se!'; } add3(add2(add1('hello,'))); //輸出:hello,compose! //以上等價于 let add = compose(add3,add2,add1); add('hello,'); ``` So,上面的`add`其實就是我們的中間件 ![](https://box.kancloud.cn/2cdd8e9b8d774fd94899f46033f2e064_988x581.png) ![](https://box.kancloud.cn/386567186ca5c62acece61d5027d4a7e_518x178.png) ## thunk ``` ... ,thunkIncrement(){ return function(dispatch,getState){ setTimeout(function(){ dispatch({type:types.INCREMENT,payload:1}) },1000); } } ... ``` ``` //處理自定義異步操作的中間件 let thunk = ({dispatch,getState})=>next=>action=>{ //處理函數的 if(typeof action == 'function'){ action(dispatch,getState); //說明是一個異步動作,將dispatch等傳給這個異步動作的函數,在異步有結果后再執行派發改變原本狀態。 }else{ next(action); //匹配下一個中間件 } }; ``` ## promise ``` ... //1) ,promiseIncrement(){ return new Promise(function(resolve,reject){ setTimeout(function(){ resolve({type:types.INCREMENT,payload:1}); //reject無法處理 },1000) }); } //2) ,payloadIncrement(){ return { type:types.INCREMENT ,payload:new Promise(function(resolve,reject){ setTimeout(function(){ if(Math.random()>.5){ resolve(100); }else{ reject(-100); } },1000) }) } } ... ``` ``` //處理promise的中間件 let promise = ({dispatch,getState})=>next=>action=>{ if(action.then&&typeof action.then === 'function'){ //是一個promise action.then(dispatch); }else if(action.payload&&action.payload.then){ action.payload.then(payload=>dispatch({...action,payload}),payload=>dispatch({...action,payload})); } else{ next(action); } }; ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看