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

資訊專欄INFORMATION COLUMN

Redux 中間件分析

littlelightss / 2287人閱讀

摘要:假設(shè)等于,其中,,是三個中間件,等于,那么可以簡化為。最終返回中的方法以及經(jīng)過中間件包裝處理過的方法。以此類推,第二個返回的就是第一個中間件的形參。根據(jù)這個的討論,在中間件頂層調(diào)用了,結(jié)果導(dǎo)致無法執(zhí)行后面的中間件。

redux 主要包含 5 個方法,分別是:

createStore

combineReducers

bindActionCreators

applyMiddleware

compose

今天主要講解下 applyMiddlewarecompose 這兩個方法。在 redux 中引入了中間件的概念,沒錯如果你使用過 Express 或者 Koa 的話,一定不會對中間件陌生。我們知道,在 Koa 中,串聯(lián)各個中間件的正是 compose 方法,所以在 redux 中也同樣使用了這個命名,作用也是串聯(lián)所有中間件。

reduce 用法

在正式講解前,我們先來看下 reduce 的用法。根據(jù) MDN 上的解釋,

reduce() 方法是對累加器和數(shù)組中的每個元素(從左到右)應(yīng)用一個函數(shù),將其減少為單個值。
arr.reduce(callback[, initialValue])
參數(shù)

callback

執(zhí)行數(shù)組中每個值的函數(shù),包含四個參數(shù):

accumulator:累加器累加回調(diào)的返回值; 它是上一次調(diào)用回調(diào)時返回的累積值,或 initialValue

currentValue:數(shù)組中正在處理的元素。

currentIndex:數(shù)組中正在處理的當(dāng)前元素的索引。 如果提供了initialValue,則索引號為0,否則為索引為1。

array:調(diào)用 reduce 的數(shù)組

initialValue

用作第一個調(diào)用 callback的第一個參數(shù)的值。 如果沒有提供初始值,則將使用數(shù)組中的第一個元素。 在沒有初始值的空數(shù)組上調(diào)用 reduce 將報錯。

返回

函數(shù)累計處理的結(jié)果

compose 分析

有了上面 reduce 的基礎(chǔ),我們再來看下 compose 的代碼。compose 的代碼很簡單,10行代碼左右,但你看到 reduce 部分的時候,估計會一臉懵逼,短短的一行代碼看上去卻很繞。

/**
 * Composes single-argument functions from right to left. The rightmost
 * function can take multiple arguments as it provides the signature for
 * the resulting composite function.
 *
 * @param {...Function} funcs The functions to compose.
 * @returns {Function} A function obtained by composing the argument functions
 * from right to left. For example, compose(f, g, h) is identical to doing
 * (...args) => f(g(h(...args))).
 */
 
export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

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

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

看注釋,它的作用應(yīng)該是

執(zhí)行 compose(f, g, h)
得到 (...args) => f(g(h(...args)))

我們來推導(dǎo)下,它是怎么得出這個結(jié)果的。假設(shè) funcs 等于 [f1, f2, f3],其中 f1f2f3 是三個中間件,(a, b) => (..args) => a(b(...args)) 等于 f,那么 funcs.reduce((a, b) => (...args) => a(b(...args))) 可以簡化為 [f1, f2, f3].reduce(f)

第 1 次執(zhí)行 f

a = f1
b = f2 
返回 (...args) => f1(f2(..args))

第 2 次執(zhí)行 f

a = (...args) => f1(f2(...args))
b = f3
返回 (...args) => a(f3(...args)) = f1(f2(f3(...args)))

通過上面的推導(dǎo),證實了先前得出的結(jié)論

compise(f, g, h) = (...args) => f(g(h(...args)))
applyMiddleware 分析

通過上面的分析,我們知道 compose 是對中間件的串聯(lián),那么 applyMiddleware 就是對中間件的應(yīng)用了。最終返回 createStore 中的方法以及經(jīng)過中間件包裝處理過的 dispatch 方法。

export default 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.`
      )
    }
    let chain = []

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

    return {
      ...store,
      dispatch
    }
  }
}

我們通過一個具體的中間件 redux-thunk,來查看它內(nèi)部到底是怎么來執(zhí)行加載的中間件的。

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === "function") {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

中間件中包含了三個箭頭函數(shù),在 applyMiddleware 中的 map 操作后,返回了第二層箭頭函數(shù),所以 chain 中存儲的是各個中間件的第二層函數(shù)。

根據(jù) compose 的分析,

dispatch = compose(...chain)(store.dispatch)
等于
dispatch = f1(f2(f3(store.dispatch)))

我們先執(zhí)行第三個中間件,并把返回結(jié)果作為第二個中間件的入?yún)⒗^續(xù)執(zhí)行,以此類推,下一個中間件的入?yún)⑹巧弦粋€中間件的返回。如果說這里第三個中間件是上面的 redux-thunk,那么函數(shù)中的 next 就是 store.dispatch,返回第三個箭頭函數(shù) action。這里返回的第三個箭頭函數(shù),就是第二個中間件的 next 形參。以此類推,第二個返回的 action 就是第一個中間件的 next 形參。但是這里都還沒真正開始執(zhí)行中間件。

當(dāng)我們外部調(diào)用 store.dispatch(action) 方法的時候,才要真正開始執(zhí)行各個中間件。首先執(zhí)行中間件 f1,當(dāng)執(zhí)行到 next 的時候,開始執(zhí)行第二個中間件 f2,以此類推直到最后一個中間件,調(diào)用原生 store.dispatch 方法。

之所以要寫這么繞,也是為了符合 redux 單一數(shù)據(jù)源的原則,applyMiddleware 的寫法保證了 action 的流向,而且每一步的數(shù)據(jù)變化都是可以追蹤的。

其他

對比了 4.0.0-beta.1 之前版本的 applyMiddleware 的區(qū)別,發(fā)現(xiàn)內(nèi)部 dispatch 從之前的 store.dispatch 改成了現(xiàn)在的直接拋出一個錯誤。根據(jù)這個 issues 的討論,在中間件頂層調(diào)用了 store.dispatch,結(jié)果導(dǎo)致無法執(zhí)行后面的中間件。這個調(diào)用應(yīng)該是在處理 map 操作的時候執(zhí)行的,此時的 applyMiddleware 還沒執(zhí)行完,store.dispatch 調(diào)用的還是原生 createStroe 中的方法才導(dǎo)致的這個問題。

另外如果在中間件中即 action 層使用 dispatch 會怎樣呢?我們知道我們可以通過 next 進(jìn)入到下個中間件,那如果調(diào)用 store.dispatch 的話又會從外層重新來一遍,假如這個中間件內(nèi)部只是粗暴的調(diào)用 store.dispatch(action) 的話,就會形成死循環(huán)。如下圖所示

參考
redux middleware 詳解

Dispatching in a middleware before applyMiddleware completes

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

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

相關(guān)文章

  • Redux原理分析

    摘要:調(diào)用鏈中最后一個會接受真實的的方法作為參數(shù),并借此結(jié)束調(diào)用鏈。總結(jié)我們常用的一般是除了和之外的方法,那個理解明白了,對于以后出現(xiàn)的問題會有很大幫助,本文只是針對最基礎(chǔ)的進(jìn)行解析,之后有機(jī)會繼續(xù)解析對他的封裝 前言 雖然一直使用redux+react-redux,但是并沒有真正去講redux最基礎(chǔ)的部分理解透徹,我覺得理解明白redux會對react-redux有一個透徹的理解。 其實,...

    sumory 評論0 收藏0
  • redux 源碼分析,實現(xiàn)一個迷你的redux

    摘要:實現(xiàn)一個先不考慮中間件,實現(xiàn)一個簡潔的實現(xiàn)是最主要的一個了,通過可以創(chuàng)建一個用來存放應(yīng)用中所有的,一個應(yīng)用只能有一個。方法是用來把每一個用方法包裹一下,因為可能只是返回一個具有屬性的對象,只有用執(zhí)行才有意義。正好可以利用的特性實現(xiàn)這個效果。 實現(xiàn)一個redux 先不考慮中間件,實現(xiàn)一個簡潔的redux 實現(xiàn)createStore createStore是redux最主要的一個API了,...

    Ashin 評論0 收藏0
  • React 項目中Redux 間件的理解

    摘要:如果想學(xué)習(xí)項目的底層建設(shè),建議先去學(xué)習(xí)官網(wǎng)案例,之后在學(xué)習(xí)的使用中間件介紹目的是提供第三方插件的模式,改變的過程。 前言 React/Redux項目結(jié)束后,當(dāng)我在研究react-router源碼的時候發(fā)現(xiàn)當(dāng)中有一部分含中間件的思想,所以才想把中間件重新梳理一遍;在之前看redux了解到中間件,redux層面中間件的理解對項目前期比較有幫助,雖然項目中后期基本可以忽略這層概念;現(xiàn)在對這部...

    amc 評論0 收藏0
  • redux淺析

    摘要:概念是一個狀態(tài)管理容器使用可以更好的管理和監(jiān)測組件之間需要通信的數(shù)據(jù)。參考源碼參考鏈接 redux概念 redux是一個狀態(tài)管理容器,使用redux可以更好的管理和監(jiān)測組件之間需要通信的數(shù)據(jù)。 redux基本原則 單一數(shù)據(jù)源 在redux中,整個應(yīng)用保持一個數(shù)據(jù)源,數(shù)據(jù)源是一個樹形的結(jié)構(gòu) 狀態(tài)只讀 狀態(tài)只讀意思是不能直接修改,需要通過dispatch action方式才可以,返回的是一...

    galois 評論0 收藏0
  • 精益 React 學(xué)習(xí)指南 (Lean React)- 3.3 理解 redux 間件

    摘要:數(shù)組為新的數(shù)組,包含了方法將新的和結(jié)合起來,生成一個新的方法返回的新增了一個方法,這個新的方法是改裝過的,也就是封裝了中間件的執(zhí)行。 書籍完整目錄 3.3 理解 Redux 中間件 showImg(https://segmentfault.com/img/bVymkt); 這一小節(jié)會講解 redux 中間件的原理,為下一節(jié)講解 redux 異步 action 做鋪墊,主要內(nèi)容為: ...

    Kerr1Gan 評論0 收藏0

發(fā)表評論

0條評論

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