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

資訊專欄INFORMATION COLUMN

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

Kerr1Gan / 3285人閱讀

摘要:數(shù)組為新的數(shù)組,包含了方法將新的和結(jié)合起來(lái),生成一個(gè)新的方法返回的新增了一個(gè)方法,這個(gè)新的方法是改裝過(guò)的,也就是封裝了中間件的執(zhí)行。

書(shū)籍完整目錄

3.3 理解 Redux 中間件

這一小節(jié)會(huì)講解 redux 中間件的原理,為下一節(jié)講解 redux 異步 action 做鋪墊,主要內(nèi)容為:

Redux 中間件是什么

使用 Redux 中間件

logger 中間件結(jié)構(gòu)分析

applyMiddleware

中間件的執(zhí)行過(guò)程

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 的中間件概念,本質(zhì)的目的是提供第三方插件的模式,自定義攔截
action -> reducer 的過(guò)程。變?yōu)?action -> middlewares -> reducer 。這種機(jī)制可以讓我們改變數(shù)據(jù)流,實(shí)現(xiàn)如異步 action ,action 過(guò)濾,日志輸出,異常報(bào)告等功能。

3.3.2 使用 Redux 中間件

Redux 提供了一個(gè)叫 applyMiddleware 的方法,可以應(yīng)用多個(gè)中間件,以日志輸出中間件為例

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 中間件結(jié)構(gòu)分析

看看 redux-logger 的源碼結(jié)構(gòu)

function createLogger(options = {}) {
  /**
   * 傳入 applyMiddleWare 的函數(shù)
   * @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 中這樣的結(jié)構(gòu) ({ getState }) => (next) => (action) => {} 看起來(lái)是很奇怪的,這種設(shè)計(jì)如果沒(méi)有 es6 的箭頭函數(shù),擴(kuò)展下來(lái)就是

/**
 * getState 可以返回最新的應(yīng)用 store 數(shù)據(jù)
 */
function ({getState}) {
    /**
     * next 表示執(zhí)行后續(xù)的中間件,中間件有可能有多個(gè)
     */
    return function (next) {
        /**
         * 中間件處理函數(shù),參數(shù)為當(dāng)前執(zhí)行的 action 
         */
        return function (action) {...}
    }
}

這樣的結(jié)構(gòu)本質(zhì)上就是為了將 middleware 串聯(lián)起來(lái)執(zhí)行,為了分析 middleware 的執(zhí)行順序,還得看看 applyMiddleware 的實(shí)現(xiàn)

3.3.4 applyMiddleware 分析

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

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 執(zhí)行過(guò)后返回一個(gè)閉包函數(shù),目的是將創(chuàng)建 store的步驟放在這個(gè)閉包內(nèi)執(zhí)行,這樣 middleware 就可以共享 store 對(duì)象。

middlewares 數(shù)組 map 為新的 middlewares 數(shù)組,包含了 middlewareAPI

compose 方法將新的 middlewaresstore.dispatch 結(jié)合起來(lái),生成一個(gè)新的 dispatch 方法

返回的 store 新增了一個(gè) dispatch 方法, 這個(gè)新的 dispatch 方法是改裝過(guò)的 dispatch,也就是封裝了中間件的執(zhí)行。

所以關(guān)鍵點(diǎn)來(lái)到了 compose 方法了,下面來(lái)看一下 compose 的設(shè)計(jì):

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 方法實(shí)際上就是利用了 Array.prototype.reduceRight 。如果對(duì) reduceRight 不是很熟悉,來(lái)看看下面的一個(gè)例子就清晰了:

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

執(zhí)行結(jié)果:

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

通過(guò)上面的 applyMiddleware 和 中間件的結(jié)構(gòu),假設(shè)應(yīng)用了如下的中間件: [A, B, C],一個(gè) action 的完整執(zhí)行流程

初始化階段

一個(gè)中間件的結(jié)構(gòu)為

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

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

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

執(zhí)行過(guò)后,middleware 變?yōu)榱?/p>

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

初始化階段二:compose 新的 dispatch

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

dispatch 的實(shí)現(xiàn)為 reduceRight, 當(dāng)一個(gè)新的 action 來(lái)了過(guò)后

/**
 * 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 的執(zhí)行過(guò)程:

初始時(shí)候

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

next 閉包: store.dispatch

第一次執(zhí)行:

previousValue(composed): composedC

currentValue(f): B

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

next 閉包 composedC

第二次執(zhí)行:

previousValue(composed): composedBC

currentValue(f): A

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

next 閉包 composedBC

最后的返回結(jié)果為 composedABC

執(zhí)行階段

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

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

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

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

store.dispatch 會(huì)執(zhí)行 reducer 生成最新的 store 數(shù)據(jù)

所有的 next 執(zhí)行完過(guò)后開(kāi)始回溯

執(zhí)行函數(shù) C 中 next 后的代碼

執(zhí)行函數(shù) B 中 next 后的代碼

執(zhí)行函數(shù) A 中 next 后的代碼

整個(gè)執(zhí)行 action 的過(guò)程為 A -> B -> C -> dispatch -> C -> B -> A

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79743.html

相關(guān)文章

  • 精益 React 學(xué)習(xí)指南Lean React)- 3.4 掌控 redux 異步

    摘要:舉例來(lái)說(shuō)一個(gè)異步的請(qǐng)求場(chǎng)景,可以如下實(shí)現(xiàn)任何異步的邏輯都可以,如等等也可以使用的和。實(shí)際上在中,一個(gè)就是一個(gè)函數(shù)。 書(shū)籍完整目錄 3.4 redux 異步 showImg(https://segmentfault.com/img/bVyou8); 在大多數(shù)的前端業(yè)務(wù)場(chǎng)景中,需要和后端產(chǎn)生異步交互,在本節(jié)中,將詳細(xì)講解 redux 中的異步方案以及一些異步第三方組件,內(nèi)容有: redu...

    JouyPub 評(píng)論0 收藏0
  • 精益 React 學(xué)習(xí)指南Lean React)- 3.5 compose redux saga

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

    Joyven 評(píng)論0 收藏0
  • 精益 React 學(xué)習(xí)指南Lean React)- 1.1 React 介紹

    摘要:?jiǎn)蜗驍?shù)據(jù)流應(yīng)用的核心設(shè)計(jì)模式,數(shù)據(jù)流向自頂向下我也是性子急的人,按照技術(shù)界的慣例,在學(xué)習(xí)一個(gè)技術(shù)前,首先得說(shuō)一句。然而的單向數(shù)據(jù)流的設(shè)計(jì)讓前端定位變得簡(jiǎn)單,頁(yè)面的和數(shù)據(jù)的對(duì)應(yīng)是唯一的我們可以通過(guò)定位數(shù)據(jù)變化就可以定位頁(yè)面展現(xiàn)問(wèn)題。 書(shū)籍完整目錄 1.1 React 介紹 showImg(https://segmentfault.com/img/bVvJgS); 1.1.1 React ...

    lsxiao 評(píng)論0 收藏0
  • 精益 React 學(xué)習(xí)指南Lean React)- 4.2 react patterns

    摘要:另外一點(diǎn)是組件應(yīng)該盡量保證獨(dú)立性,避免和外部的耦合,使用全局事件造成了和外部事件的耦合。明確的職責(zé)分配也增加了應(yīng)用的確定性明確只有組件能夠知道狀態(tài)數(shù)據(jù),且是對(duì)應(yīng)部分的數(shù)據(jù)。 書(shū)籍完整目錄 4.2 react patterns 修改 Props Immutable data representation 確定性 在 getInitialState 中使用 props 私有狀態(tài)和...

    Berwin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<