摘要:再學(xué)習(xí)的過程中這塊感覺很燒腦所以對(duì)它的原理進(jìn)行整理有一些比較基礎(chǔ)的先不整理以日志中間件為例以下的這種寫法屬于柯里化的知識(shí)以上的代碼可以解釋成源碼假如說里有三個(gè)一個(gè)保存了狀態(tài)和方法的對(duì)象這個(gè)對(duì)應(yīng)的就是的通過閉包的形式引用外部的執(zhí)行了方法返回了
再學(xué)習(xí)redux的過程中,Middleware這塊感覺很燒腦,所以對(duì)它的原理進(jìn)行整理
有一些比較基礎(chǔ)的先不整理,
以日志中間件為例
//以下的這種寫法屬于柯里化的知識(shí) const logger = state => next => action =>{ console.log("dispatch", action); next(action); console.log("nextState",store.getState); }
以上的代碼可以解釋成
var logger = function logger(state) { return function (next) { return function (action) { console.log("dispatch", action); next(action); console.log("nextState", store.getState); }; }; };
//applyMiddleware 源碼 export default function applyMiddleware(...middlewares) { //假如說 middlewares 里有三個(gè)mid1,mid2,mid3 return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) let dispatch = store.dispatch let chain = [] //一個(gè)保存了store狀態(tài),和dispatch方法的對(duì)象 這個(gè)對(duì)應(yīng)的就是logger 的store const middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action)//通過閉包的形式引用外部的dispatch } //執(zhí)行了middleware方法,返回了需要next參數(shù)的方法 的數(shù)組 chain = middlewares.map(middleware => middleware(middlewareAPI)) //假如chain 為[f1,f2,f3,f4,f5,f6,f7] //那么下面這句話的翻譯就是這樣 dispatch = f1(f2(f3(f4(f5(f6(f7(store.dispatch))))))) //就是將chain中的函數(shù)串聯(lián)到一起,這種組合從最里面開始執(zhí)行,返回的結(jié)果作為上一個(gè)函數(shù)的參數(shù),一直向外執(zhí)行 //就是相當(dāng)于從chain函數(shù)的最右側(cè)到最左側(cè)執(zhí)行 //compose(...chain) 返回的是一個(gè)匿名函數(shù) function compose(...funcs) funcs就是chain //return funcs.reduce((a, b) => (...args) => a(b(...args))) 這里的args就是store.dispatch dispatch = compose(...chain)(store.dispatch) //dispatch = f1(f2(f3(f4(f5(f6(f7(store.dispatch))))))) //當(dāng)調(diào)用dispatch的時(shí)候就依次執(zhí)行 return { ...store, dispatch// 這個(gè)是處理過的dispatch } } }
chain = middlewares.map(middleware => middleware(middlewareAPI))
這里可以看出來,在日志中間件中的第一層的store就是middlewareAPI
并且將第二層返回到chain的數(shù)組中
這就相當(dāng)于當(dāng)初的store => next => action =>{...}變成了next => action =>{...}
dispatch = compose(...chain)(store.dispatch) 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))) }
這一步相當(dāng)于把chain數(shù)組中函數(shù),通過處理得到一種類似于層層嵌套的結(jié)構(gòu)f1(f2(f3(f4(args))))
所以dispatch = A(B(C(store.dispatch))
單個(gè)中間件較為簡(jiǎn)單,所以拿三個(gè)中間件做例子
經(jīng)上面所述
//因?yàn)閽侀_store,剩下的中間件的結(jié)構(gòu)類似于下面這種 function A1(next){ return function A2(action){ next(action) } } function B1(next){ return function B2(action){ next(action) } } function C1(next){ return function C2(action){ next(action) } }
//dispatch = A(B(C(store.dispatch)) //這種結(jié)構(gòu)會(huì)先執(zhí)行最內(nèi)部的函數(shù),也就是C(store.dispatch)這一塊 //當(dāng)執(zhí)行了C 返回的是一個(gè)函數(shù) function C2(action){ store.dispatch(action) } //返回值最為他的外層函數(shù)的參數(shù)next next = function C2(action){ store.dispatch(action) } //此時(shí)的結(jié)構(gòu)類似于這種 dispatch = A(B(function C2(action) { store.dispatch(action) }(action) ) ) //接下來執(zhí)行B,返回了 next = function C2(action){ function C2(action){ store.dispatch(action) }(action) } //此時(shí)的結(jié)構(gòu)類似于這種 dispatch = A(function B2(action) { function C2(action){ store.dispatch(action) }(action) }(action) ) //接下來執(zhí)行A,返回了 dispatch = function A2(action){ function B2(action) { function C2(action){ store.dispatch(action) }(action) }(action) }(action)
最后返回新的store
總結(jié)
調(diào)用applyMiddleware 傳入n個(gè)中間件的數(shù)組
用一個(gè)middlewareAPI保存當(dāng)前的store.getState,和dispatch所指向的函數(shù)
迭代中間件數(shù)組,并執(zhí)行一遍,將middlewareAPI作為最外層的store,并且返回一個(gè)相當(dāng)于next函數(shù)的數(shù)組
將數(shù)組整理成嵌套的函數(shù)體,并將store.dispatch傳入最內(nèi)側(cè)的函數(shù)的next,并返回經(jīng)過處理的dispatch (dispatch是一個(gè)經(jīng)過處理的函數(shù),是一個(gè)嵌套了多層的函數(shù),其最里面調(diào)用的是store.dispatch)
返回一個(gè)新的store
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/108025.html
摘要:每種可被解析的格式必須具有由詞匯及語法規(guī)則組成的特定的文法,稱為上下文無關(guān)文法。解析解析器,每個(gè)標(biāo)識(shí)都有特定的正則進(jìn)行解析。開發(fā)者可以將腳本標(biāo)識(shí)為,以使其不阻塞文檔解析,并在文檔解析結(jié)束后執(zhí)行。 瀏覽器組成 用戶界面-地址欄、按鈕之類的 瀏覽器引擎-用來查詢及操作渲染引擎的接口 渲染引擎-顯示請(qǐng)求的內(nèi)容 網(wǎng)絡(luò)-進(jìn)行網(wǎng)絡(luò)請(qǐng)求 ui后端-用來滬指選擇框、對(duì)話框的基本組件 js解析器 數(shù)據(jù)...
摘要:每種可被解析的格式必須具有由詞匯及語法規(guī)則組成的特定的文法,稱為上下文無關(guān)文法。解析解析器,每個(gè)標(biāo)識(shí)都有特定的正則進(jìn)行解析。開發(fā)者可以將腳本標(biāo)識(shí)為,以使其不阻塞文檔解析,并在文檔解析結(jié)束后執(zhí)行。 瀏覽器組成 用戶界面-地址欄、按鈕之類的 瀏覽器引擎-用來查詢及操作渲染引擎的接口 渲染引擎-顯示請(qǐng)求的內(nèi)容 網(wǎng)絡(luò)-進(jìn)行網(wǎng)絡(luò)請(qǐng)求 ui后端-用來滬指選擇框、對(duì)話框的基本組件 js解析器 數(shù)據(jù)...
摘要:通過以上四個(gè)步驟,瀏覽器完成從用戶處接收用戶要訪問的域名到從域名服務(wù)主機(jī)處獲取數(shù)據(jù)的整個(gè)過程。概念解析指別名記錄也被稱為規(guī)范名字可以理解為對(duì)域名設(shè)置別名。詳細(xì)可以參考一些名詞解釋 傳統(tǒng)的網(wǎng)絡(luò)訪問形式為: showImg(http://segmentfault.com/img/bVcqjG); 由上圖可見,用戶訪問未使用CDN緩存網(wǎng)站的過程為: 用戶向?yàn)g覽器提供要訪問的域名; 瀏...
摘要:使用指定的參數(shù)調(diào)用構(gòu)造函數(shù),并將綁定到新創(chuàng)建的對(duì)象。由構(gòu)造函數(shù)返回的對(duì)象就是表達(dá)式的結(jié)果。情況返回以外的基本類型實(shí)例中只能訪問到構(gòu)造函數(shù)中的屬性,和情況完全相反,結(jié)果相當(dāng)于沒有返回值。 定義 new 運(yùn)算符創(chuàng)建一個(gè)用戶定義的對(duì)象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象的實(shí)例。 ——(來自于MDN) 舉個(gè)栗子 function Car(color) { this.color = co...
閱讀 2471·2021-11-23 09:51
閱讀 1273·2021-11-22 13:54
閱讀 3500·2021-09-24 10:31
閱讀 1187·2021-08-16 10:46
閱讀 3710·2019-08-30 15:54
閱讀 770·2019-08-30 15:54
閱讀 2952·2019-08-29 17:17
閱讀 3247·2019-08-29 15:08