摘要:接下來我們來看看源碼中的模塊是怎么應(yīng)用中間件的。如何實(shí)現(xiàn)中間件操作的。新的會(huì)從第一個(gè)中間件開始觸發(fā),這樣,在我們調(diào)用的時(shí)候,就會(huì)將中間件走一遍了。函數(shù)如果存在多個(gè)中間件,直接使用方法將各個(gè)中間件嵌套起來。
從redux-thunk引出思考
在使用redux-thunk進(jìn)行異步action書寫的時(shí)候,我經(jīng)常好奇redux到底如何運(yùn)作,讓asyncAction成為可能
為了探究,我們必須看一下redux-thunk的源碼了。幸運(yùn)的是redux-thunk的源碼很少。。。至于為什么,下面立馬講解。
redux-thunk的源碼// redux-thunk source code 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;
從源碼可以看出該中間件僅僅只是一個(gè)工廠函數(shù),輸出了一個(gè)嵌套工廠函數(shù)的工廠函數(shù),那個(gè)最終參數(shù)帶著next的返回函數(shù),就是redux所需要適應(yīng)的中間件。
以es6箭頭語法看來可能比較麻煩,我們可以試著把這個(gè)代碼直接轉(zhuǎn)成es5的形式看看。
function createThunkMiddleware(extraArgument) { return function (storeOrFakeStore) { var dispatch = storeOrFakeStore.dispatch; var getState = storeOrFakeStore.getState; return function (next) { return function (action) { return action(dispatch, getState, extraArgument); } return next(action); } }; }
從這個(gè)源碼可以看出,本身中間件是會(huì)接受當(dāng)前store或者一個(gè)fakeStore(這個(gè)fakeStore可能僅僅只承載了store的兩個(gè)api,dispatch和getState),并將dispatch和getState這兩個(gè)store的方法傳進(jìn)可能執(zhí)行異步操作的action函數(shù)里。這樣,action完成異步操作以后,同樣被賦予了dispatch的權(quán)利,就能夠?qū)顟B(tài)通過action流轉(zhuǎn)到下一個(gè)場(chǎng)景了。
那同學(xué)們又會(huì)問了,這個(gè)next是個(gè)啥?恩,其實(shí)這個(gè)next其實(shí)就是下一個(gè)要處理action的中間件,畢竟中間件是一個(gè)接著一個(gè)的對(duì)吧。如果大家寫過koa或者express應(yīng)該對(duì)這個(gè)next會(huì)熟悉很多。
接下來我們來看看react源碼中的createStore模塊是怎么應(yīng)用中間件的。
我們使用createStore api創(chuàng)建store的時(shí)候發(fā)生了什么applyMiddleware同樣也是一個(gè)工廠,如果讀者您用過redux中間件的話,你應(yīng)該知道redux創(chuàng)建store是怎樣創(chuàng)建的
const store = createStore( reducer, applyMiddleware(...middleware) )
以下是createStore的源碼,我們只看相關(guān)的一部分
export default function createStore(reducer, preloadedState, enhancer) { if (typeof preloadedState === "function" && typeof enhancer === "undefined") { enhancer = preloadedState preloadedState = undefined } if (typeof enhancer !== "undefined") { if (typeof enhancer !== "function") { throw new Error("Expected the enhancer to be a function.") } return enhancer(createStore)(reducer, preloadedState) } ... }
結(jié)合store的聲明和使用,我們可以知道redux的第三個(gè)參數(shù)可以接受一個(gè)叫做增強(qiáng)器的東西,如果存在增強(qiáng)器,則直接調(diào)用增強(qiáng)器方法,返回新的store并增強(qiáng)redux的功能。而使用中間件的時(shí)候,redux將存在的applyMiddleware工廠方法作為增強(qiáng)器應(yīng)用在了redux上。
applyMiddleware api如何實(shí)現(xiàn)中間件操作的。export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) let dispatch = store.dispatch let chain = [] const middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
applyMiddleware工廠函數(shù)對(duì)傳入的中間件進(jìn)行了compose操作,使中間件互相之間呈嵌套的形式,這樣在中間件里的next函數(shù)就可以next()執(zhí)行下去了。。。新的dispatch會(huì)從第一個(gè)中間件開始觸發(fā),這樣,在我們調(diào)用store.dispatch的時(shí)候,就會(huì)將中間件走一遍了。
// compose函數(shù) export default function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } // 如果存在多個(gè)中間件,直接使用reduce方法將各個(gè)中間件嵌套起來。 // 于是我們?cè)谑褂弥虚g件的時(shí)候就要注意了,中間件本質(zhì)是一個(gè)攔截操作 // 如果我們有兩個(gè)中間件對(duì)某一個(gè)類型的action先后做了攔截,我們必須注意 // 在createStore的時(shí)候插入中間件的順序,中間件方法的執(zhí)行是有序的。 return funcs.reduce((a, b) => (...args) => a(b(...args))) }你也可以制作一個(gè)中間件
怎么樣,redux的源碼簡(jiǎn)單嗎?簡(jiǎn)單到同學(xué)們也能自己開發(fā)中間件,現(xiàn)在大家自己也可以動(dòng)手寫自己的react中間件了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/84517.html
摘要:現(xiàn)在關(guān)于最新版本新特性的宣傳講解已經(jīng)鋪天蓋地了。測(cè)試場(chǎng)景是反復(fù)操作數(shù)組,這個(gè)反復(fù)操作有所講究,我們計(jì)劃持續(xù)不斷地改變數(shù)組的某一項(xiàng)而不是整個(gè)數(shù)組的大范圍變動(dòng)。代碼和性能測(cè)試在使用開發(fā)時(shí),相信很多開發(fā)者在搭配函數(shù)式的狀態(tài)管理框架使用。 現(xiàn)在關(guān)于 React 最新 v16 版本新特性的宣傳、講解已經(jīng)鋪天蓋地了。你最喜歡哪一個(gè) new feature?截至目前,組件構(gòu)建方式已經(jīng)琳瑯滿目。那么,...
摘要:內(nèi)部機(jī)制探秘和文末附彩蛋和源碼這篇文章比較偏基礎(chǔ),但是對(duì)入門內(nèi)部機(jī)制和實(shí)現(xiàn)原理卻至關(guān)重要。當(dāng)然也需要明白一些淺顯的內(nèi)部工作機(jī)制。當(dāng)改變出現(xiàn)時(shí),相比于真實(shí)更新虛擬的性能優(yōu)勢(shì)非常明顯。直到最終,會(huì)得到完整的表述樹的對(duì)象。 React 內(nèi)部機(jī)制探秘 - React Component 和 Element(文末附彩蛋demo和源碼) 這篇文章比較偏基礎(chǔ),但是對(duì)入門 React 內(nèi)部機(jī)制和實(shí)現(xiàn)原...
摘要:前端每周清單半年盤點(diǎn)之與篇前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。與求同存異近日,宣布將的構(gòu)建工具由遷移到,引發(fā)了很多開發(fā)者的討論。 前端每周清單半年盤點(diǎn)之 React 與 ReactNative 篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為...
摘要:前端日?qǐng)?bào)精選劉海打理指北中的錯(cuò)誤處理模式與反模式譯圖解和譯你并不知道中文裝飾器讓你的代碼更簡(jiǎn)潔眾成翻譯第期每個(gè)程序員第一份工作前應(yīng)該知道的件事中的不變性眾成翻譯寫的一次小結(jié)掘金內(nèi)部機(jī)制探秘和文末附彩蛋和源碼前端雜談開發(fā)實(shí)戰(zhàn) 2017-09-30 前端日?qǐng)?bào) 精選 iPhone X 劉海打理指北React16中的錯(cuò)誤處理ES6 Promise:模式與反模式「譯」圖解 ArrayBuffer...
摘要:使用新的易用的類定義,歸根結(jié)底也是要?jiǎng)?chuàng)建構(gòu)造函數(shù)和修改原型。首先,它把構(gòu)造函數(shù)當(dāng)成單獨(dú)的函數(shù)且包含類屬性集。該節(jié)點(diǎn)還儲(chǔ)存了指向父類的指針引用,該父類也并儲(chǔ)存了構(gòu)造函數(shù),屬性集和及父類引用,依次類推。 原文請(qǐng)查閱這里,略有刪減,本文采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第...
閱讀 739·2023-04-26 02:08
閱讀 2778·2021-11-18 10:02
閱讀 3543·2021-11-11 16:55
閱讀 2409·2021-08-17 10:13
閱讀 2963·2019-08-30 15:53
閱讀 738·2019-08-30 15:44
閱讀 2618·2019-08-30 11:10
閱讀 1819·2019-08-29 16:57