redux-promise
解析這個(gè)中間的用法,以及原理
源碼
import isPromise from 'is-promise';
import { isFSA } from 'flux-standard-action';
export default function promiseMiddleware({ dispatch }) {
return next => action => {
/**
* 判斷是不是標(biāo)準(zhǔn)的FSA
*/
if (!isFSA(action)) {
/**
* 判斷是不是promise,
* 如果是則執(zhí)行,只會(huì)處理resolve的值,
* 反之交給下一個(gè)中間件
*/
return isPromise(action) ? action.then(dispatch) : next(action);
}
// 是標(biāo)準(zhǔn)的FSA, 判斷是不是一個(gè)promise
return isPromise(action.payload)
/**
* 1.promise的時(shí)候,執(zhí)行then,同時(shí)捕獲異常,
* 在處理這兩種情況以后,會(huì)分別添加另外一個(gè)約束error
* 這我們需要在reducer里面還需要判斷error的值,
* 做不同的處理
*
* 2. 如果不是promise則交給下一個(gè)中間件
*
* */
? action.payload
.then(result => dispatch({ ...action, payload: result }))
.catch(error => {
dispatch({ ...action, payload: error, error: true });
return Promise.reject(error);
})
: next(action);
};
}
用法
雖然官方文檔上面并沒有舉例是如何使用(至這篇文章編寫時(shí)),但其實(shí)文檔中已經(jīng)說明的很清晰了,主要分為以下兩種情況:
-
1.當(dāng)中間接收到的是一個(gè)Promise實(shí)例,會(huì)dispatch掉resoved的值,對(duì)于reject的結(jié)果并不做任何處理。舉例來說:
const testRes = () => { return new Promise((res, rej) => { res({ type: 'TEST_RESOLVE' }) }); } store.dispatch(testRes()); const testRej = () => { return new Promise((res, rej) => { rej({ type: 'TEST_REJECT' }) }); } store.dispatch(testRes());上面的兩個(gè)例子,只有第一個(gè)會(huì)直接
dipatch,第二個(gè)不會(huì)有任何操作,其實(shí)查看源碼就知道if (!isFSA(action)) { return isPromise(action) ? action.then(dispatch) : next(action); }action.then只接收了一個(gè)函數(shù),所以不會(huì)處理reject的值,不過從幾行代碼,我們還可以得到幾點(diǎn)信息。- 中間件內(nèi)部是會(huì)自動(dòng)地幫我們調(diào)用dispatch
-
resolve的值會(huì)被當(dāng)做diapatch的參數(shù)被重新分發(fā) -
resolve的值并不會(huì)繼續(xù)流轉(zhuǎn)到交給下一個(gè)中間件了
-
2.當(dāng)中間件接收的是一個(gè)符合
FSA的action,會(huì)接著判斷action.payload是不是一個(gè)promise,如果不是則直接轉(zhuǎn)給下一個(gè)中間件,是則調(diào)用then,同時(shí)使用catch捕獲異常,這里出現(xiàn)兩種情況,查看源碼:action.payload .then(result => dispatch({ ...action, payload: result })) .catch(error => { dispatch({ ...action, payload: error, error: true }); return Promise.reject(error); })- 當(dāng)
promise的狀態(tài)變成resolved的時(shí)候回進(jìn)入then里面,并且重新dispatch(action) - 當(dāng)
promise的狀態(tài)變成rejected的時(shí)候回進(jìn)入catch里面,并且重新dispatch(action), 同時(shí)會(huì)在action里面加一個(gè)error
從上面兩種情況來看,當(dāng)
action.payload為promise的時(shí)候,會(huì)被重新分發(fā),并且不會(huì)走到下一個(gè)中間件。 - 當(dāng)
建議
從上面的源碼我們看出:
源碼簡(jiǎn)單易懂,使用promise來解決異步,省去了額外的學(xué)習(xí)成本。但是同樣由于過于簡(jiǎn)單,無法完成我們項(xiàng)目中一些特定的需求,比如我們想請(qǐng)求一個(gè)列表數(shù)據(jù),在請(qǐng)求的時(shí)候我們想做一些loading的動(dòng)畫,由于這個(gè)中間件是直接攔截掉action, 并最終經(jīng)過判斷處理同樣只會(huì)分發(fā)一次,這樣在解決上面的應(yīng)用場(chǎng)景中,不是很適合,同樣我們判斷請(qǐng)求成功或者失敗的時(shí)候需要額外的判斷error,其實(shí)是增增加了額外的約束。