<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                &emsp;&emsp;Redux的中間件(Middleware)遵循了即插即用的設計思想,出現在Action到達Reducer之前(如圖10所示)的位置。中間件是一個固定模式的獨立函數,當把多個中間件像管道那樣串聯在一起時,前一個中間件不但能將其輸出傳給下一個中間件作為輸入,還能中斷整條管道。在引入中間件后,既能擴展Redux的功能,也能增強dispatch()函數,適應不同的業務需求,例如通過中間件記錄日志、報告奔潰或處理異步請求等。 :-: ![](https://img.kancloud.cn/13/11/131117d1ebd7c3c4a7013d00e8cfe2d9_1109x76.png =600x) 圖10 中間件管道 ## 一、開發模式 &emsp;&emsp;在設計中間件函數時,會遵循一個固定的模式,如下代碼所示,使用了柯里化、高階函數等函數式編程中的概念。 ~~~js function middleware(store) { return function(next) { return function(action) { return next(action); }; }; } ~~~ &emsp;&emsp;middleware()函數接收一個Store實例,返回值是一個接收next參數的函數。其中next也是一個函數,用來將控制權轉移給下一個中間件,從而實現了中間件之間的串聯,它會返回一個處理Action對象的函數。由于閉包的作用,在這最內層的函數中,依然能調用外層的對象和函數,例如訪問action所攜帶的數據、執行store中的dispatch()或getState()方法等。示例中的middleware()函數只是單純的將接收到的action對象轉交給后面的中間件,沒有對其做額外的處理。 &emsp;&emsp;之所以將中間件函數寫成層層嵌套的模式,有以下幾個原因。 &emsp;&emsp;(1)擴展Redux需要遵循函數式編程的設計思想。 &emsp;&emsp;(2)柯里化讓中間件更容易處理數據流,即便于形成數據處理管道。 &emsp;&emsp;(3)每個中間件的職責單一(即函數代碼盡量少),通過嵌套組合完成復雜功能。 &emsp;&emsp;利用ES6中的箭頭函數能將middleware()函數改寫得更加簡潔,如下所示。 ~~~js const middleware = store => next => action => { return next(action); }; ~~~ ## 二、applyMiddleware() &emsp;&emsp;Redux提供了組織中間件的applyMiddleware()函數,在閱讀過此函數的源碼(如下所示)之后,才能更好的理解中間件的開發模式。 ~~~js function applyMiddleware(...middlewares) { return createStore => (...args) => { const store = createStore(...args); let dispatch = () => { throw new Error( "Dispatching while constructing your middleware is not allowed. " + "Other middleware would not be applied to this dispatch." ); }; const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) }; const chain = middlewares.map(middleware => middleware(middlewareAPI)); dispatch = compose(...chain)(store.dispatch); return { ...store, dispatch }; }; } ~~~ **1)源碼分析** &emsp;&emsp;接下來會分析函數中的代碼,為了便于理解,在說明中還會給出相應的語句。 &emsp;&emsp;(1)利用剩余參數(...middlewares)的方式,applyMiddleware()函數可以接收任意多個中間件。 &emsp;&emsp;(2)返回一個接收createStore參數的函數,在函數體中調用Redux的createStore()函數,得到一個store實例。 ~~~js const store = createStore(...args); ~~~ &emsp;&emsp;(3)middlewareAPI變量包含了中間件需要的參數,即store.getState()和dispatch()方法。 ~~~js const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) }; ~~~ &emsp;&emsp;(4)將middlewareAPI變量傳遞給每個中間件并調用一次,再將返回的函數組成一個新數組。 ~~~js const chain = middlewares.map(middleware => middleware(middlewareAPI)); ~~~ &emsp;&emsp;(5)通過compose()增強dispatch()方法,compose()是Redux內置的函數,可從右向左合成多個函數,例如compose(f1, f2, f3)(arg)相當于f1(f2(f3(arg)))。 ~~~js dispatch = compose(...chain)(store.dispatch); ~~~ &emsp;&emsp;(6)最終得到一個對象,包含store實例的方法和增強后的dispatch()方法。 ~~~js return { ...store, dispatch }; ~~~ **2)使用方式** &emsp;&emsp;applyMiddleware()函數有兩種使用方式,下面用一個例子來演示,先定義兩個中間件:m1和m2,以及一個Reducer函數:caculate()。 ~~~js const m1 = store => next => action => { console.log("m1"); return next(action); }; const m2 = store => next => action => { console.log("m2"); return next(action); }; function caculate(previousState = {digit:0}, action) { let state = Object.assign({}, previousState); switch (action.type) { case "ADD": state.digit += 1; break; case "MINUS": state.digit -= 1; } return state; } ~~~ &emsp;&emsp;(1)applyMiddleware()是一個三級柯里化的函數,如果要使用,那么可以像下面這樣調用,先傳兩個中間件,再傳createStore()函數,最后傳caculate()函數。 ~~~js let store = applyMiddleware(m1, m2)(createStore)(caculate); ~~~ &emsp;&emsp;(2)applyMiddleware()函數還可以作為createStore()的最后一個參數,如下代碼所示,第一個參數是caculate()函數,第二個參數是applyMiddleware()函數的結果。 ~~~js let store = createStore(caculate, applyMiddleware(m1, m2)); ~~~ &emsp;&emsp;在applyMiddleware()函數的內部,chain數組的值是\[m1(next), m2(next)\],由m1和m2返回的包含next參數的函數組成。增強后的dispatch()方法通過m1(m2(store.dispatch))得到,具體如下所示。 ~~~js dispatch = action => { console.log("m1"); return next(action); }; ~~~ &emsp;&emsp;當調用store實例的dispatch()方法(如下代碼所示)時,會先輸出“m1”;然后調用next()函數,也就是m2(next),輸出“m2”;最后調用m2中的next()函數,也就是dispatch()方法。注意,不能在中間件中直接調用dispatch()方法,以免造成死循環。 ~~~js store.dispatch({ type: "ADD" }); ~~~ ## 三、redux-thunk &emsp;&emsp;如果要在Redux中處理異步請求,那么可以借助中間件實現,目前市面上已有很多封裝好的中間件可供使用,例如redux-thunk、redux-promise或redux-saga等。本節將著重講解redux-thunk中間件,其核心代碼如下所示。 ~~~js function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === "function") { return action(dispatch, getState, extraArgument); } return next(action); }; } ~~~ &emsp;&emsp;首先檢測action的類型,如果是函數,那么就直接調用并將dispatch、getState和extraArgument作為參數傳入;否則就調用next參數,轉移控制權。redux-thunk其實擴展了dispatch()方法,使其參數既可以是JavaScript對象,也可以是函數。 &emsp;&emsp;接下來用一個簡單的例子演示redux-thunk的用法,如下代碼所示,首先通過import引入redux-thunk,并定義一個異步Action。 ~~~js import thunk from "redux-thunk"; function asynAction() { return dispatch => { fetch("server.php").then( response => response.json(), error => console.log(error) ).then(data => { dispatch(data); //{type: "ADD"} }); }; } ~~~ &emsp;&emsp;然后讓asynAction()函數返回一個接收dispatch參數的函數,在函數體內通過fetch()函數請求服務端的資源,再利用得到的Promise處理獲取到的數據。在第二個then()方法中,data參數被賦為{type: "ADD"},也就是server.php響應的數據,其代碼如下所示。 ~~~php <?php $json = [ 'type' => 'ADD' ]; echo json_encode($json); ~~~ &emsp;&emsp;再接入redux-thunk中間件,即將thunk傳給applyMiddleware()函數,最后發送一個異步Action,如下所示。 ~~~js let store = createStore(caculate, applyMiddleware(thunk)); store.dispatch(asynAction()); ~~~ ***** > 原文出處: [博客園-React躬行記](https://www.cnblogs.com/strick/category/1455720.html) [知乎專欄-React躬行記](https://zhuanlan.zhihu.com/pwreact) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <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>

                              哎呀哎呀视频在线观看