react 中介軟體相關的一些原始碼解析
零、隨便說說中介軟體
在react的使用中,我們可以將資料放到redux,甚至將一些資料相關的業務邏輯放到redux,這樣可以簡化我們元件,也更方便元件抽離、封裝、複用,只是redux不能很好的處理非同步,當我們獲取介面資料的時候,redux就滿足不了我們的需要。然後,中介軟體就出來了,使用中介軟體可以滿足我們非同步獲取資料,當然也可以幹其他的事;
我們都知道一個數據更新,經過component >> action >> dispatch >> reducers >> state >> store >> component,這樣一個過程。其實,中介軟體的本質就是 把非同步的這種情況單獨的拿出來處理,然後還是把資料經過redux處理了。也就是說做中介軟體的關鍵是先把正常的action 和 非同步的action 區分出來,從上邊的流程看也只能是action >> dispatch 這一步了。
下邊看看中介軟體相關的一些原始碼,從createStore開始:
一、createStore
const createStore = (reducers, initialState, enhancer) => { if (typeof initialState === 'function' && typeof enhancer === 'undefined') { enhancer = initalState; initialState = undefined; } if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { //校驗enhancer是否為函式,如果不是函式則丟擲異常 throw new Error('Expected the enhancer to be a function.') } //如果enhancer存在且為函式,那麼則返回如下呼叫,如果enhancer為applyMiddleware,那麼呼叫則 //是applyMiddleware(createStore)(reducer, preloadedState)。後面講applyMiddleware再詳細講。 return enhancer(createStore)(reducer, preloadedState) } .... // 下邊就是沒有中介軟體的時候,返回一些state的方法如:getState, dispatch... }
這就是做了個區分,有中介軟體和沒中介軟體的區分,有中介軟體返回的是中介軟體程式碼: enhancer(createStore)(reducer, preloadedState) ,沒有就直接返回一些方法;
二、applyMiddleware
const applyMiddleware = (...middlewares) => (createStore) => (reducer, initial, enhancer) => { const store = createStore(reducer, initial, enhancer); let dispatch = store.dispatch; let chain = []; const middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) }; chain = middlewares.map(middleware => middleware(middlewareAPI));// a dispatch = compose(...chain)(store.dispatch); // b return { ...store, dispatch }; }
看名字就可以知道這是應用中介軟體的一個方法,他是將中介軟體 middlewares 和 store 結合返回一個新的store物件,實際上是對 dispatch 的重寫;
結合上邊的 createStore 原始碼我們可以看到,當有中介軟體的時候 createStore 返回的實際上就是 applyMiddleware 的一個執行結果,從引數看是從第二層的方法開始的,那是因為,我們在執行 createStore之前,會有下面的一步操作:
const enhancer = compose(applyMiddleware(...middlewares)) const store = createStore(reducer, enhancer)
其實可以看到在 applyMiddleware 中利用 createState 重新生成了 store,並對 dispatch 進行了重寫:先將每一箇中間件都執行一次,引數是 middlewareAPI ,然後將返回的陣列, 藉助於 compose,以原生 dispatch 為引數執行,返回新的 dispatch,最後替換 store 裡的 dispatch 並作為新的 store 返回;這個返回結果實際上就是 createStore 中,有中介軟體傳入時的返回結果。
可能會對 dispatch 重寫的過程會不太清楚,下邊看看 compose 原始碼:
三、compose
const compose = (...middlewares) => { if (middlewares.length === 0) { return arg => arg; } else { const last = middlewares[middlewares.length - 1]; const reset = middlewares.slice(0, -1); return (args) => rest.reduceRight((composed, f) => f(composed), last(args)) } }
結合著 applyMiddleware 看這個原始碼會更好沒理解一點。(reducerRight 方法不熟的朋友,百度一下)
當傳入中介軟體陣列的時候,返回的是一個帶引數的方法, 引數就是相當於上面的 dispatch ,取出最後一箇中間件執行,並最為 reducerRight 的 初始值,執行reducerRight 方法;
四、中介軟體的方法middleware
const middleware = ({ state, dispatch}) => (next) => (action) => { if (typeof action === 'funtion') { return net(action); } dispatch(action); }
中介軟體的本質:判斷你要處理的情況,執行你想要執行的方法,如果是非同步,我們 action 通常是方法,所以就執行next,如果不是非同步執行的就是原生 dispatch;
中介軟體的第一層是在 applyMiddleware 中執行的(標註a處),第二層是 applyMiddleware 中 compose 中執行的(標註b處),其實 next 就是原生的 dispatch 或者已經重寫的 dispatch (即 middleware 中最後一層的方法);
五、沒有了
到目前為止這個中介軟體相關的原始碼算是搞完了,理解這些感覺寫個中介軟體基本上沒問題,推薦看看 redux-thunk 原始碼其實很簡單,和第四步的差不多;
有一箇中間件的小Dome:https://github.com/wayaha/react-demos-middleware
敢不敢點個星!!!