跳至主要内容

[Redux] middleware 筆記

Middleware 是在 action 進入到 reducer 之前,可以讓我們做一些介入 action 的時間點:

透過 Middleware 我們可以延遲、記錄(log)、調整或停止 action

在 Redux 中並沒有限制 Middleware 的數量,因此我們可以有很多個 middleware,每個 middleware 會檢查這是不是自己需要處理的 action,如果不是就會傳給下一個 middleware 繼續處理。

打造 Redux Promise Middleware

Redux Promise Middleware,會在 action 進來的時候判斷這個 action 是不是包含有 Promise 物件,如果沒有的話會直接傳遞到進到下一個 middleware;如果有 Promise 物件的話,則會進入這個 middleware,這個 middleware 會等到 Promise resolvereject 之後,會把 payload 帶有 Promise 的結果後,重新發送一個新的 action,這個 action 會從頭開始,再次經過所有的 middleware,但因為這次它已經不帶有 Promise 物件,因此會直接被傳遞到下一個 middleware。

當 Redux Promise Middleware 等到 Promise resolve 或 reject 之後,是會發送一個新的 action,這個 action 會從第一個 middleware 重新走起,而不是把處理完的資料直接丟到 reducers

boilerplate

Middleware 的樣版長的像這樣:

// ./middlwares/async.js

// 簡化後的寫法:
export default ({ dispatch }) => next => action => { ... }

// 完整的寫法如下:
// export default function({ dispatch }) {
// return function(next) {
// return function(action) {

// };
// };
// }

Sample Code

// ./middlwares/async.js

export default ({ dispatch }) => (next) => (action) => {
// 檢查看看 action 的 payload 屬性是否是 Promise 物件

// 如果不是 Promise 物件(用 then 檢查),那麼將 action 傳送到下一個 middleware
if (!action.payload || !action.payload.then) {
// return 並不是必要的,但可以確保 return 之後的程式碼不會被執行到
return next(action);
}

// 如果是的話,等待 Promise 被 resolved,
// 然後建立一個帶有 resolved 資料的新 action,並發送(dispatch)它
action.payload
.then((response) => {
const newAction = { ...action, payload: response };
dispatch(newAction);
})
.catch((error) => {
const newAction = { ...action, payload: error };
dispatch(newAction);
});
};

放入 Middleware 到 Redux 中

import { createStore, applyMiddleware, composeEnhancers } from 'redux';

// 有使用 Redux Devtools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducers, composeEnhancers(applyMiddleware(asyncMiddleware)));

// 不使用 Redux Devtools
const store = createStore(rootReducers, applyMiddleware(asyncMiddleware));