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

資訊專欄INFORMATION COLUMN

Redux中間件原理詳解

Shihira / 3446人閱讀

摘要:當(dāng)你應(yīng)用了中間件,在觸發(fā)一個(gè)操作的時(shí)候,操作就會(huì)經(jīng)過先經(jīng)過中間件,最終再形成。以其中兩個(gè)中間件為例,說明下,一個(gè)觸發(fā)一個(gè)動(dòng)作的時(shí)候,代碼的執(zhí)行邏輯。

為了解析中間件,先看一下幾個(gè)中間件是什么樣子,怎么用,運(yùn)行起來的原理是什么?

1、中間件是什么樣子的 1.2 thunk中間件
function createThunkMiddleware(extraArgument) {

  return ({ dispatch, getState }) => next => action => {
    // 如果是函數(shù),就執(zhí)行函數(shù)
    if (typeof action === "function") {
        return action(dispatch, getState, extraArgument);
    }
    // 如果不是,執(zhí)行下一個(gè)中間件
    return next(action);
  };
}

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

export default thunk;
1.2promise中間件
import isPromise from "is-promise";
import { isFSA } from "flux-standard-action";

export default function promiseMiddleware({ dispatch }) {
  return next => action => {
    if (!isFSA(action)) {
      return isPromise(action) ? action.then(dispatch) : next(action);
    }

    return isPromise(action.payload)
      ? action.payload
          .then(result => dispatch({ ...action, payload: result }))
          .catch(error => {
            dispatch({ ...action, payload: error, error: true });
            return Promise.reject(error);
          })
      : next(action);
  };
}
1.3logger中間件
const defaultLogger = ({ dispatch, getState } = {}) => {
  if (typeof dispatch === "function" || typeof getState === "function") {
    return createLogger()({ dispatch, getState });
  }
};
function createLogger(options = {}) {
  const loggerOptions = Object.assign({}, defaults, options);

  const {
    logger,
    stateTransformer,
    errorTransformer,
    predicate,
    logErrors,
    diffPredicate,
  } = loggerOptions;

  if (typeof logger === "undefined") {
    return () => next => action => next(action);
  }

  import { logger } from "redux-logger"
  const store = createStore(
      reducer,
      applyMiddleware(logger))
    
  import { createLogger } from "redux-logger"
  const logger = createLogger({
      // ...options
    });
  const store = createStore(
      reducer,
      applyMiddleware(logger));
      
  return () => next => action => next(action);
  }

  const logBuffer = [];

  return ({ getState }) => next => (action) => {
    if (typeof predicate === "function" && !predicate(getState, action)) {
      return next(action);
    }
    const logEntry = {};

    logBuffer.push(logEntry);

    logEntry.started = timer.now();
    logEntry.startedTime = new Date();
    logEntry.prevState = stateTransformer(getState());
    logEntry.action = action;

    let returnedValue;
    if (logErrors) {
      try {
        returnedValue = next(action);
      } catch (e) {
        logEntry.error = errorTransformer(e);
      }
    } else {
      returnedValue = next(action);
    }

    logEntry.took = timer.now() - logEntry.started;
    logEntry.nextState = stateTransformer(getState());

    const diff = loggerOptions.diff && typeof diffPredicate === "function"
      ? diffPredicate(getState, action)
      : loggerOptions.diff;

    printBuffer(logBuffer, Object.assign({}, loggerOptions, { diff }));
    logBuffer.length = 0;

    if (logEntry.error) throw logEntry.error;
    return returnedValue;
  };
}
export { defaults, createLogger, defaultLogger as logger };

export default defaultLogger;
2、怎么使用中間件
const store = createStore(rootReducer, initialState, 
    applyMiddleware(thunk),
    ... ...
);

簡(jiǎn)單來說,createStore做了這么件事:
目的:根據(jù)你傳入的reducer和初始狀態(tài)initialState生成初始化store,并提供了一些列操作的接口,像dispatch等
怎么做的呢?參考Redux-creatStore/compose
本文重點(diǎn)講解中間件的執(zhí)行過程和原理

3、中間件運(yùn)行原理

中間件的執(zhí)行原理和koa中間件的執(zhí)行原理類似,但是不是洋蔥型的,而是半個(gè)洋蔥,因?yàn)閞edux是單向執(zhí)行的,走過去就完事了。
當(dāng)你應(yīng)用了中間件,在觸發(fā)一個(gè)action操作的時(shí)候,action操作就會(huì)經(jīng)過先經(jīng)過中間件,最終再形成dispatch(action)。
以其中兩個(gè)中間件為例,說明下,一個(gè)觸發(fā)一個(gè)action動(dòng)作的時(shí)候,代碼的執(zhí)行邏輯。
thunk:是允許dispatch一個(gè)函數(shù),而不是一個(gè)對(duì)象
假如說異步打印一個(gè)日志。

3.1 中間件的內(nèi)部邏輯
const store = createStore(reducer, preloadedState, enchancer);

// 如果沒有中間件,正常觸發(fā)一個(gè)action;
// 如果有中間件的時(shí)候 creatStore內(nèi)部的執(zhí)行邏輯是這樣的
// enchancer 就是你應(yīng)用的中間件,調(diào)用applyMiddleware得到的組合中間件

function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
  
    // 該創(chuàng)建的store還是要?jiǎng)?chuàng)建的,只傳入了兩個(gè)參數(shù),沒有中間件,得到的是正常的store
    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.`
      )
    }
    // 把getState、dispatch傳給中間件
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    // 下面方法返回來了一個(gè)函數(shù)數(shù)組,中間件被剝離到
    // next => {}
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    // 再執(zhí)行下面的,中間件就被剝離到
    // action => {}
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

// 下面得到的結(jié)果是 
// 假設(shè)中間件為 a b
// a(b(store.dispatch))
return enchancer(createStore)(reducer, preloadedState);

// 結(jié)合上面thunk的源碼
({ dispatch, getState }) => next => action => {
    if (typeof action === "function") {
        return action(dispatch, getState);
    }
    return next(action);
  };

經(jīng)過上面的操作后,經(jīng)過中間件包裝后的store是什么樣子
假設(shè)中間件為 a b c
沒有中間件的時(shí)候是這樣的

store = {
    dispatch,
    ... ...,
    subscribe,
    getState
}

經(jīng)過中間包裝后,store變成了

store = {
    dispatch: a(b((store.dispatch))),
    ... ...,
    subscribe,
    getState
}

總結(jié)起來就是給每一個(gè)中間件配發(fā)了一個(gè)原始store的dispatch,中間件函數(shù)嵌套執(zhí)行

3.2 觸發(fā)一個(gè)action時(shí),執(zhí)行邏輯

假設(shè)觸發(fā)一個(gè)異步打印日志的功能

應(yīng)用中間件

const store = createStore(rootReducer, initialState, 
    applyMiddleware(thunk)
);

經(jīng)過上面的操作,現(xiàn)在的store應(yīng)該是

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

action函數(shù)

當(dāng)執(zhí)行這個(gè)logNext的時(shí)候,返回一個(gè)函數(shù),函數(shù)的參數(shù)是dispatch和getState兩個(gè)。

const logNext = () => (dispatch, getState) => {
    setTimeout(
        dispatch({
            type: "LOG",
            payload: {
                content: "這是一條異步日志"
            }})
        ,5000);
}

執(zhí)行過程

---->
store.dispatch(logNext())  // 傳了一個(gè)函數(shù),然后執(zhí)行一個(gè)函數(shù)
----> 
(dispatch, getState) => {
    setTimeout(
        dispatch({
            type: "LOG",
            payload: {
                content: "這是一條異步日志"
            }})
        ,5000);
} 
---->

可以看出來,redux-thunk就是一個(gè)封裝函數(shù),允許store.dispatch一個(gè)函數(shù)
如果有多個(gè)中間件,執(zhí)行過程是什么樣子的?重點(diǎn)在next(action),next是什么呢?
next就是每一個(gè)中間件要做的事情

next => action => {}

明白了么?

附錄 compsoe
// compose本身并不改變函數(shù)的執(zhí)行,將函數(shù)組合后又返回了一個(gè)函數(shù)
    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)))
    }

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

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

相關(guān)文章

  • redux-saga框架使用詳解及Demo教程

    摘要:通過創(chuàng)建將所有的異步操作邏輯收集在一個(gè)地方集中處理,可以用來代替中間件。 redux-saga框架使用詳解及Demo教程 前面我們講解過redux框架和dva框架的基本使用,因?yàn)閐va框架中effects模塊設(shè)計(jì)到了redux-saga中的知識(shí)點(diǎn),可能有的同學(xué)們會(huì)用dva框架,但是對(duì)redux-saga又不是很熟悉,今天我們就來簡(jiǎn)單的講解下saga框架的主要API和如何配合redux框...

    Nosee 評(píng)論0 收藏0
  • 詳解react、redux、react-redux之間的關(guān)系

    摘要:或者兄弟組件之間想要共享某些數(shù)據(jù),也不是很方便傳遞獲取等。后面要講到的就是通過讓各個(gè)子組件拿到中的數(shù)據(jù)的。所以,確實(shí)和沒有什么本質(zhì)關(guān)系,可以結(jié)合其他庫正常使用。 本文介紹了react、redux、react-redux之間的關(guān)系,分享給大家,也給自己留個(gè)筆記,具體如下: React 一些小型項(xiàng)目,只使用 React 完全夠用了,數(shù)據(jù)管理使用props、state即可,那什么時(shí)候需要引入...

    xioqua 評(píng)論0 收藏0
  • redux middleware 詳解

    摘要:執(zhí)行完后,獲得數(shù)組,,它保存的對(duì)象是圖中綠色箭頭指向的匿名函數(shù),因?yàn)殚]包,每個(gè)匿名函數(shù)都可以訪問相同的,即。是函數(shù)式編程中的組合,將中的所有匿名函數(shù),,組裝成一個(gè)新的函數(shù),即新的,當(dāng)新執(zhí)行時(shí),,從左到右依次執(zhí)行所以順序很重要。 前言 It provides a third-party extension point between dispatching anaction, and t...

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

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

0條評(píng)論

Shihira

|高級(jí)講師

TA的文章

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