對(duì)react中間件的理解

一、是什么?
中間件(Middleware)在計(jì)算機(jī)中,是介于應(yīng)用系統(tǒng)和系統(tǒng)軟件之間的一類(lèi)軟件,它使用系統(tǒng)軟件所提供的基礎(chǔ)服務(wù)(功能),銜接網(wǎng)絡(luò)應(yīng)用上的各個(gè)部分或不同的應(yīng)用,能夠達(dá)到資源共享、功能共享的目的
我們知道redux整個(gè)工作流程,當(dāng)action發(fā)出之后,reducer立即算出state,整個(gè)過(guò)程是一個(gè)同步的操作。
那么如果要支持異步操作,或者支持錯(cuò)誤處理、日志監(jiān)控,就可以使用上中間件。

Redux中,中間件就是放在就是在dispatch過(guò)程,在分發(fā)action進(jìn)行攔截處理,如上圖
其本質(zhì)上一個(gè)函數(shù),對(duì)store.dispatch方法進(jìn)行了改造,在發(fā)出 Action和執(zhí)行 Reducer這兩步之間,添加了其他功能
二、常用的中間件
redux-thunk:用于異步操作
redux-logger:用于日志記錄
redux-promise
redux-saga
上述的中間件都需要通過(guò)applyMiddlewares進(jìn)行注冊(cè),作用是將所有的中間件組成一個(gè)數(shù)組,依次執(zhí)行,然后作為第二個(gè)參數(shù)傳入到createStore中
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import createLogger rom 'redux-logger'
const logger = createLogger()
const store = createStore(reducer, applyMiddleware(thunk, logger)) // 按順序執(zhí)行 從右到左
logger實(shí)現(xiàn)
// 自己修改dispatch,增加logger
let next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
next(action)
console.log('next state', store.getState())
}
redux-thunk
添加了thunk中間件之后,就可以進(jìn)行異步操作
redux-thunk是官網(wǎng)推薦的異步處理中間件
默認(rèn)情況下的dispatch(action),action需要是一個(gè)JavaScript的對(duì)象
redux-thunk中間件會(huì)判斷你當(dāng)前傳進(jìn)來(lái)的數(shù)據(jù)類(lèi)型,如果是一個(gè)函數(shù),將會(huì)給函數(shù)傳入?yún)?shù)值(dispatch,getState)dispatch函數(shù)用于我們之后再次派發(fā)actiongetState函數(shù)考慮到我們之后的一些操作需要依賴(lài)原來(lái)的狀態(tài),用于讓我們可以獲取之前的一些狀態(tài)
所以dispatch可以寫(xiě)成下述函數(shù)的形式:
const getHomeMultidataAction = () => {
return (dispatch) => {
axios.get("http://xxx.xx.xx.xx/test").then(res => {
const data = res.data.data;
dispatch(changeBannersAction(data.banner.list));
dispatch(changeRecommendsAction(data.recommend.list));
})
}
}

dispatch(addTodo(text)) dispatch(addTodoAsync(text))
redux數(shù)據(jù)流圖:

三、實(shí)現(xiàn)原理
首先看看applyMiddlewares的源碼
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}
}
}
所有中間件被放進(jìn)了一個(gè)數(shù)組chain,然后嵌套執(zhí)行,最后執(zhí)行store.dispatch。可以看到,中間件內(nèi)部(middlewareAPI)可以拿到getState和dispatch這兩個(gè)方法
在上面的學(xué)習(xí)中,我們了解到了redux-thunk的基本使用
內(nèi)部會(huì)將dispatch進(jìn)行一個(gè)判斷,然后執(zhí)行對(duì)應(yīng)操作,原理如下:
function patchThunk(store) {
letnext = store.dispatch;
function dispatchAndThunk(action) {
if (typeof action === "function") {
action(store.dispatch, store.getState);
} else {
next(action);
}
}
store.dispatch = dispatchAndThunk;
}
實(shí)現(xiàn)一個(gè)日志輸出的原理也非常簡(jiǎn)單,如下:
let next = store.dispatch;
function dispatchAndLog(action) {
console.log("dispatching:", addAction(10));
next(addAction(5));
console.log("新的state:", store.getState());
}
store.dispatch = dispatchAndLog;
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
React項(xiàng)目動(dòng)態(tài)設(shè)置title標(biāo)題的方法示例
這篇文章主要介紹了React項(xiàng)目動(dòng)態(tài)設(shè)置title標(biāo)題的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
React Router 如何使用history跳轉(zhuǎn)的實(shí)現(xiàn)
這篇文章主要介紹了React Router 如何使用history跳轉(zhuǎn)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
react-navigation 如何判斷用戶(hù)是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法
本篇文章主要介紹了react-navigation 如何判斷用戶(hù)是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
React 實(shí)現(xiàn)車(chē)牌鍵盤(pán)的示例代碼
這篇文章主要介紹了React 實(shí)現(xiàn)車(chē)牌鍵盤(pán)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
Input標(biāo)簽自動(dòng)校驗(yàn)功能去除實(shí)現(xiàn)
這篇文章主要為大家介紹了Input標(biāo)簽的自動(dòng)拼寫(xiě)檢查功能去除實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
react-router browserHistory刷新頁(yè)面404問(wèn)題解決方法
本篇文章主要介紹了react-router browserHistory刷新頁(yè)面404問(wèn)題解決方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-12-12
React中如何實(shí)現(xiàn)受控組件與非受控組件
在 React 開(kāi)發(fā)里,組件可分為受控組件和非受控組件,這篇文章將為大家介紹一下它們的實(shí)現(xiàn)原理,方法,區(qū)別,作用和應(yīng)用場(chǎng)景是什么,希望對(duì)大家有所幫助2025-03-03

