redux-promise解析

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è)中間件。

建議

從上面的源碼我們看出:
源碼簡(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í)是增增加了額外的約束。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容