国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

精益 React 學習指南 (Lean React)- 3.3 理解 redux 中間件

Kerr1Gan / 3291人閱讀

摘要:數組為新的數組,包含了方法將新的和結合起來,生成一個新的方法返回的新增了一個方法,這個新的方法是改裝過的,也就是封裝了中間件的執行。

書籍完整目錄

3.3 理解 Redux 中間件

這一小節會講解 redux 中間件的原理,為下一節講解 redux 異步 action 做鋪墊,主要內容為:

Redux 中間件是什么

使用 Redux 中間件

logger 中間件結構分析

applyMiddleware

中間件的執行過程

3.3.1 Redux 中間件是什么

Redux moddleware provides a third-party extension point between dispatching an action, and the moment it reaches the reducer.

redux 提供了類似后端 Express 的中間件概念,本質的目的是提供第三方插件的模式,自定義攔截
action -> reducer 的過程。變為 action -> middlewares -> reducer 。這種機制可以讓我們改變數據流,實現如異步 action ,action 過濾,日志輸出,異常報告等功能。

3.3.2 使用 Redux 中間件

Redux 提供了一個叫 applyMiddleware 的方法,可以應用多個中間件,以日志輸出中間件為例

import { createStore, applyMiddleware } from "redux"
import createLogger from "redux-logger"
import rootReducer from "./reducers"

const loggerMiddleware = createLogger()
const initialState = {}

return createStore(
    rootReducer,
    initialState,
    applyMiddleware(
      loggerMiddleware
    )
  )
3.3.3 logger 中間件結構分析

看看 redux-logger 的源碼結構

function createLogger(options = {}) {
  /**
   * 傳入 applyMiddleWare 的函數
   * @param  {Function} { getState      }) [description]
   * @return {[type]}      [description]
   */
  return ({ getState }) => (next) => (action) => {
    let returnedValue;
    const logEntry = {};
    logEntry.prevState = stateTransformer(getState());
    logEntry.action = action;
    // .... 
    returnedValue = next(action);
    // ....
    logEntry.nextState = stateTransformer(getState());
    // ....
    return returnedValue;
  };
}

export default createLogger;

Logger 中這樣的結構 ({ getState }) => (next) => (action) => {} 看起來是很奇怪的,這種設計如果沒有 es6 的箭頭函數,擴展下來就是

/**
 * getState 可以返回最新的應用 store 數據
 */
function ({getState}) {
    /**
     * next 表示執行后續的中間件,中間件有可能有多個
     */
    return function (next) {
        /**
         * 中間件處理函數,參數為當前執行的 action 
         */
        return function (action) {...}
    }
}

這樣的結構本質上就是為了將 middleware 串聯起來執行,為了分析 middleware 的執行順序,還得看看 applyMiddleware 的實現

3.3.4 applyMiddleware 分析

下面是 applyMiddleware 完整的代碼,參數為 middlewares 數組:

import compose from "./compose"

/**
 * Creates a store enhancer that applies middleware to the dispatch method
 * of the Redux store. This is handy for a variety of tasks, such as expressing
 * asynchronous actions in a concise manner, or logging every action payload.
 *
 * See `redux-thunk` package as an example of the Redux middleware.
 *
 * Because middleware is potentially asynchronous, this should be the first
 * store enhancer in the composition chain.
 *
 * Note that each middleware will be given the `dispatch` and `getState` functions
 * as named arguments.
 *
 * @param {...Function} middlewares The middleware chain to be applied.
 * @returns {Function} A store enhancer applying the middleware.
 */
export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer)
    var dispatch = store.dispatch
    var chain = []

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

applyMiddleware 執行過后返回一個閉包函數,目的是將創建 store的步驟放在這個閉包內執行,這樣 middleware 就可以共享 store 對象。

middlewares 數組 map 為新的 middlewares 數組,包含了 middlewareAPI

compose 方法將新的 middlewaresstore.dispatch 結合起來,生成一個新的 dispatch 方法

返回的 store 新增了一個 dispatch 方法, 這個新的 dispatch 方法是改裝過的 dispatch,也就是封裝了中間件的執行。

所以關鍵點來到了 compose 方法了,下面來看一下 compose 的設計:

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}

可以看到 compose 方法實際上就是利用了 Array.prototype.reduceRight 。如果對 reduceRight 不是很熟悉,來看看下面的一個例子就清晰了:

/**
 * [description]
 * @param  {[type]} previousValue [前一個項]
 * @param  {[type]} currentValue  [當前項]
 */
[0, 1, 2, 3, 4].reduceRight(function(previousValue, currentValue, index, array) {
  return previousValue + currentValue;
}, 10);

執行結果:

# previousValue currentValue return value
第一次 10 4 14
第二次 14 3 17
第三次 17 2 19
第四次 19 1 20
第五次 20 0 20
3.3.5 理解中間件的執行過程

通過上面的 applyMiddleware 和 中間件的結構,假設應用了如下的中間件: [A, B, C],一個 action 的完整執行流程

初始化階段

一個中間件的結構為

function ({getState}) {
    return function (next) {
        return function (action) {...}
    }
}

初始化階段一:middlewares map 為新的 middlewares

chain = middlewares.map(middleware => middleware(middlewareAPI))

執行過后,middleware 變為了

function (next) {
    return function (action) {...}
}

初始化階段二:compose 新的 dispatch

const newDispatch = compose(newMiddlewares)(store.dispatch)

dispatch 的實現為 reduceRight, 當一個新的 action 來了過后

/**
 * 1. 初始值為: lastMiddleware(store.dispatch)
 * 2. previousValue: composed
 * 3. currentValue: currentMiddleware
 * 4. return value: currentMiddleware(composed) => newComposed
 */
rest.reduceRight((composed, f) => f(composed), last(...args))
composed 流程

reduceRight 的執行過程:

初始時候

initialValue: composedC = C(store.dispatch) = function C(action) {}

next 閉包: store.dispatch

第一次執行:

previousValue(composed): composedC

currentValue(f): B

return value: composedBC = B(composedC) = function B(action){}

next 閉包 composedC

第二次執行:

previousValue(composed): composedBC

currentValue(f): A

return value: composedABC = A(composedBC) = function A(action){}

next 閉包 composedBC

最后的返回結果為 composedABC

執行階段

dispatch(action) 等于 composedABC(action) 等于執行 function A(action) {...}

在函數 A 中執行 next(action), 此時 A 中 nextcomposedBC,那么等于執行 composedBC(action) 等于執行 function B(action){...}

在函數 B 中執行 next(action), 此時 B 中 nextcomposedC,那么等于執行 composedC(action) 等于執行 function C(action){...}

在函數 C 中執行 next(action), 此時 C 中 nextstore.dispatch 即 store 原生的 dispatch, 等于執行 store.dispatch(action)

store.dispatch 會執行 reducer 生成最新的 store 數據

所有的 next 執行完過后開始回溯

執行函數 C 中 next 后的代碼

執行函數 B 中 next 后的代碼

執行函數 A 中 next 后的代碼

整個執行 action 的過程為 A -> B -> C -> dispatch -> C -> B -> A

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79743.html

相關文章

  • 精益 React 學習指南Lean React)- 3.4 掌控 redux 異步

    摘要:舉例來說一個異步的請求場景,可以如下實現任何異步的邏輯都可以,如等等也可以使用的和。實際上在中,一個就是一個函數。 書籍完整目錄 3.4 redux 異步 showImg(https://segmentfault.com/img/bVyou8); 在大多數的前端業務場景中,需要和后端產生異步交互,在本節中,將詳細講解 redux 中的異步方案以及一些異步第三方組件,內容有: redu...

    JouyPub 評論0 收藏0
  • 精益 React 學習指南Lean React)- 3.5 compose redux saga

    摘要:通過可以實現很多有趣的簡潔的控制。這里默認使用到了的一個特性,如果某一個任務成功了過后,其他任務都會被。組合是的內關鍵字,使用的場景是一個。 書籍完整目錄 3.5 compose redux sages showImg(https://segmentfault.com/img/bVyoVa); 基于 redux-thunk 的實現特性,可以做到基于 promise 和遞歸的組合編排,而...

    Joyven 評論0 收藏0
  • 精益 React 學習指南Lean React)- 1.1 React 介紹

    摘要:單向數據流應用的核心設計模式,數據流向自頂向下我也是性子急的人,按照技術界的慣例,在學習一個技術前,首先得說一句。然而的單向數據流的設計讓前端定位變得簡單,頁面的和數據的對應是唯一的我們可以通過定位數據變化就可以定位頁面展現問題。 書籍完整目錄 1.1 React 介紹 showImg(https://segmentfault.com/img/bVvJgS); 1.1.1 React ...

    lsxiao 評論0 收藏0
  • 精益 React 學習指南Lean React)- 4.2 react patterns

    摘要:另外一點是組件應該盡量保證獨立性,避免和外部的耦合,使用全局事件造成了和外部事件的耦合。明確的職責分配也增加了應用的確定性明確只有組件能夠知道狀態數據,且是對應部分的數據。 書籍完整目錄 4.2 react patterns 修改 Props Immutable data representation 確定性 在 getInitialState 中使用 props 私有狀態和...

    Berwin 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<