摘要:作為目前最火的模式實現(xiàn)之一,它有很多的點值得研究。這個函數(shù)既然要用于,也就是說它接收一個形式為的函數(shù),對其一層層嵌套形式為。這個會在開始時發(fā)起一個,并在這個時發(fā)起另一個成功或失敗的。為了方便起見,會返回這個讓調(diào)用者可以等待。
Redux作為目前最火的Flux模式實現(xiàn)之一,它有很多的點值得研究。今天我們首先來看看它的Middleware。
熟悉Express或者koa的朋友對Middleware的概念一定不陌生。例如Express中是這樣使用一個中間件的:
var app = express(); app.use(function(req, res, next) { console.log("%s %s", req.method, req.url); next(); });
app.use中的方法,可以在其后面的http VERB調(diào)用之前,對request對象和response對象進行處理,然后通過調(diào)用next方法將處理過程轉(zhuǎn)發(fā)到下一中間件或者通過返回響應(yīng)來結(jié)束處理過程。(之后有機會的話再寫一寫Node和Express)。
我理解的所謂中間件其實就是,通過類似裝飾者模式的形式,用代碼預(yù)處理的方式,保證原本處理問題的函數(shù)(或方法)調(diào)用不變。
Redux中的中間件可以使得在用戶調(diào)用store.dispatch之后,先對參數(shù)state和actions進行預(yù)處理,再讓真正的store.dispatch調(diào)用,以確保reducer的純度(函數(shù)式編程的概念)不變。
Redux中提供了applyMiddleware方法,它的源碼只有十幾行,真的是非常精妙。
下面我們就研究一下它的源代碼。
applyMiddleware方法applyMiddleware(...middlewares){ return next => (reducer, initialState){ var store = next(reducer, initialState), dispatch = store.dispatch, chain = [], middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) }; chain = middlewares.map(middleware => middleware(middlewareAPI)); dispatch = compose(...chain, store.dispatch); return { ...store, dispatch } } }
這段代碼的意思就是,appleMiddleware方法接收一個Middleware列表,以applyMiddleware(middleware1, middleware2, middleware3)的形式調(diào)用(參見ES6的rest參數(shù)語法),然后再將創(chuàng)建store的方法傳入(我想這個原因是Redux不僅僅可以在React中使用,也可以適用于任何Flux模式的框架和庫),然后就會發(fā)生神奇的事情。
這兩次調(diào)用(假設(shè):var newCreateSore = applyMiddleware(middleware1, middleware2)(createStore))會產(chǎn)生一個新的創(chuàng)建Store的方法,但是它改造了原本Store的dispatch方法,讓這個dispatch可以做原生dispatch不能做的事情,這樣我們就可以訂制dispatch的行為,從而實現(xiàn)了中間件的概念。
故而,newCreateStore將作為createStore的替代方法,使用newCreateStore會產(chǎn)生帶有中間件的store。
在最內(nèi)層是如何實現(xiàn)中間件的調(diào)用的呢?讓我們繼續(xù)研究。
首先我們用傳入的next(一個可以創(chuàng)建Store的函數(shù)),創(chuàng)建一個原始的store,并且取出其原生的store.dispatch方法和store.getState方法成為一個對象,作為參數(shù)傳入中間件函數(shù)中,讓其第一次包裝這個類似store的對象,并返回新的函數(shù)。
然后我們使用compose函數(shù),將這些包裝過后的返回的函數(shù)一個接一個的嵌套調(diào)用。
這里補充一下compose的概念:
假設(shè)有若干函數(shù)f1, f2, f3...,compose指的是類似f1(f2(f3(x)))的調(diào)用方式,這在函數(shù)式編程中很常見。
(這里的compose函數(shù)是redux中的一個方法,這里我們不上它的源碼,有興趣的朋友可以直接看源碼。)
被嵌套在compose最內(nèi)層的是原生的store.dispatch方法,這里我們就一層層的將其包裝,在中間件函數(shù)中,我們可以利用store的其他方法,比如store.dispatch和store.getState,做一些有意思的事情,比如實現(xiàn)一個記錄state改變的日志中間件。
中間件函數(shù)從上面的分析中,我們不難寫一個符合要求的中間件函數(shù)。
首先中間件函數(shù)需要接受一個middlewareAPI,如果使用ES6的語法,這里可以看成是接收一個{dispatch, getState}的形式的參數(shù),這樣我們就能在內(nèi)層使用這兩個方法。
接收middlewareAPI參數(shù)之后,中間件函數(shù)返回另一個函數(shù)(為方便后面解釋,假設(shè)返回的函數(shù)為dispatch n)。這個函數(shù)既然要用于compose,也就是說它接收一個形式為dispatch的函數(shù),對其一層層嵌套(形式為dispatch1(dispatch2(dispatch3(dispatch))))。在其內(nèi)部我們可以在之前的dispatch調(diào)用之前和之后,進行一些邏輯的處理。
寫一個簡單的記錄state日志的中間件如下:
var middlewareLogger = ({getState}) => next => action => { console.log(getState()); next(action); console.log(getState()); }
怎么樣,是不是特別簡單?
再寫一個異步操作的中間件:
const readyStatePromise = store => next => action => { if (!action.promise) { return next(action) } function makeAction(ready, data) { let newAction = Object.assign({}, action, { ready }, data) delete newAction.promise return newAction } next(makeAction(false)) return action.promise.then( result => next(makeAction(true, { result })), error => next(makeAction(true, { error })) ) }
這個中間件讓你可以發(fā)起帶有一個 { promise } 屬性的特殊 action。這個 middleware 會在開始時發(fā)起一個 action,并在這個 promise resolve 時發(fā)起另一個成功(或失?。┑?action。為了方便起見,dispatch 會返回這個 promise 讓調(diào)用者可以等待。
結(jié)束文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/90852.html
摘要:中間件對異步的實現(xiàn)非常重要,因為在之前的文章中我們談到,是一個行為抽象,只是一個對象,是一個純函數(shù),不應(yīng)該有調(diào)用和副作用的操作。這個函數(shù)并不需要保持純凈,它還可以帶有副作用,包括執(zhí)行異步請求。那么如何在中進行網(wǎng)絡(luò)請求標(biāo)準(zhǔn)的做法是使用。 在之前的淺談Flux架構(gòu)及Redux實踐一文中我們初步的談及了Redux的數(shù)據(jù)流思想,并做了一個簡單的加減器。但是還沒有接觸到Redux更多常用的場景,...
摘要:大多的初學(xué)者都會使用中間件來處理異步請求,其理解簡單使用方便具體使用可參考官方文檔。源碼的源碼非常簡潔,出去空格一共只有行,這行中如果不算上則只有行。官方文檔中的一節(jié)講解的非常好,也確實幫我理解了中間件的工作原理,非常推薦閱讀。 總覺得文章也應(yīng)該是有生命力的,歡迎關(guān)注我的Github上的博客,這里的文章會依據(jù)我本人的見識,逐步更新。 大多redux的初學(xué)者都會使用redux-thunk...
摘要:好處就是不再需要能夠處理異步的中間件了。不過,它是一個研究中間件很好的范本。執(zhí)行它,返回的是由第二層函數(shù)組成的中間件數(shù)組。也就是說呀同學(xué)們,除了最后一個中間件的是原始的之外,倒數(shù)往前的中間件傳入的都是上一個中間件的邏輯函數(shù)。 本文是『horseshoe·Redux專題』系列文章之一,后續(xù)會有更多專題推出來我的 GitHub repo 閱讀完整的專題文章來我的 個人博客 獲得無與倫比的閱...
摘要:中的是實際的調(diào)用順序是和傳入中間件順序相反的實際的執(zhí)行是次序是。這個返回的函數(shù)是中倒數(shù)第二個函數(shù)的參數(shù),也就是參數(shù)源碼參考 showImg(https://segmentfault.com/img/remote/1460000013998406?w=720&h=159); showImg(https://segmentfault.com/img/remote/1460000013998...
摘要:最后看一下這時候執(zhí)行返回,如下調(diào)用執(zhí)行循序調(diào)用第層中間件返回即調(diào)用第層中間件返回即調(diào)用根返回即調(diào)用一個例子讀懂上文提到是個柯里化函數(shù),可以看成是將所有函數(shù)合并成一個函數(shù)并返回的函數(shù)。 由于一直用業(yè)界封裝好的如redux-logger、redux-thunk此類的中間件,并沒有深入去了解過redux中間件的實現(xiàn)方式。正好前些時間有個需求需要對action執(zhí)行時做一些封裝,于是借此了解了下...
閱讀 2837·2021-11-22 15:11
閱讀 3559·2021-09-28 09:43
閱讀 2906·2019-08-30 13:05
閱讀 3445·2019-08-30 11:18
閱讀 1459·2019-08-29 16:34
閱讀 1319·2019-08-29 13:53
閱讀 2922·2019-08-29 11:03
閱讀 1673·2019-08-29 10:57