亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解redux異步操作實(shí)踐

 更新時間:2018年08月15日 09:33:06   作者:yjy5264  
這篇文章主要介紹了詳解redux異步操作實(shí)踐,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

一、redux基礎(chǔ)

redux

  1. 通過 dispatch(action) -> 中間件 -> reducer處理數(shù)據(jù) -> 改變store -> 使用subscribe()監(jiān)聽store改變更新視圖 的方式管理狀態(tài)
  2. 將所有狀態(tài)存儲在一個store對象里面
  3. reducer為純函數(shù),而異步操作由于結(jié)果的不確定性所以含有副作用,所以需要特殊處理

react-redux

  1. 容器組件,負(fù)責(zé)管理數(shù)據(jù)和業(yè)務(wù)邏輯,不負(fù)責(zé)UI呈現(xiàn)
  2. UI組件,提供UI呈現(xiàn),無狀態(tài)即不使用this.state,狀態(tài)全部由this.props提供
  3. 由connect生成容器組件,每次store改變會調(diào)用connect,connect接收兩個參數(shù): mapStateToProps, mapDispatchToProps
  4. mapStateToProps,將狀態(tài)映射到UI組件的props
  5. mapDispatchToProps,將dispatch方法映射到UI組件的props
  6. Provider組件,使用content API將store從頂層開始傳到每一層component供connect使用

二、redux處理異步的中間件

redux-thunk

  1. redux-thunk中間件允許action是一個方法
  2. 中間件收到action后會執(zhí)行action方法并將結(jié)果提供給reducer
  3. action混亂導(dǎo)致不易維護(hù)

redux-saga

  1. saga會監(jiān)聽action并基于這個action執(zhí)行Effects操作
  2. Effects提供靈活的API,包括阻塞、非阻塞調(diào)用,取消、等待、race等操作
  3. 方便隔離并執(zhí)行異步操作,并易于測試

三、redux-request-async-middleware

先從redux文檔中的異步action說起,每個接口調(diào)用需要dispatch三個同步action,分別是:

  1. 一種通知 reducer 請求開始的 action。對于這種 action,reducer 可能會切換一下 state 中的 isFetching 標(biāo)記。以此來告訴 UI 來顯示加載界面。
  2. 一種通知 reducer 請求成功的 action。對于這種 action,reducer 可能會把接收到的新數(shù)據(jù)合并到 state 中,并重置 isFetching。UI 則會隱藏加載界面,并顯示接收到的數(shù)據(jù)。
  3. 一種通知 reducer 請求失敗的 action。對于這種 action,reducer 可能會重置 isFetching。另外,有些 reducer 會保存這些失敗信息,并在 UI 里顯示出來。

也就是一個接口發(fā)起是這樣的

dispatch(fetchPostsRequest(subject));
fetch(url).then(res => {
  dispatch(fetchPostsSuccess(subject, res));
}).catch(e => {
  dispatch(fetchPostsFailure(subject, e));
})

而我做的事情只是將這個操作封裝進(jìn)中間件里,特殊的地方在于:

  1. 所有的異步請求共用這三個action
  2. 用subject來區(qū)分是哪一個請求
  3. 將所有的結(jié)果都放到store.requests里

中間件源碼

export const reduxRequest = store => next => action => {
  let result = next(action);
  let { type, subject, model } = action;
  let _next = action.next;
  if(type === FETCH_POSTS_REQUEST) {
    model().then(response => {
      _next && _next(response);
      store.dispatch(fetchPostsSuccess(subject, response));
    }).catch(error => {
      console.error(error);
      store.dispatch(fetchPostsFailure(subject, error));
    });
  }
  return result
};
  1. 和redux-thunk一樣,將方法放進(jìn)action里
  2. 中間件攔截FETCH_POSTS_REQUEST action,并進(jìn)行異步處理

reducer源碼

export const requests = (state = {}, action) => {
  switch (action.type) {
    case FETCH_POSTS_REQUEST:
      return assign({},
        state,
        {
          [action.subject]: {
            isFetching: true,
            state: 'loading',
            subject: action.subject,
            response: null,
            error: null,
          }
        }
      );
    case FETCH_POSTS_FAILURE:
      return assign({},
        state,
        {
          [action.subject]: {
            isFetching: false,
            state: 'error',
            subject: action.subject,
            response: state[action.subject].response,
            error: action.error,
          }
        }
      );
    case FETCH_POSTS_SUCCESS:
      return assign({},
        state,
        {
          [action.subject]: {
            isFetching: false,
            state: 'success',
            subject: action.subject,
            response: action.response,
          }
        }
      );
    case FETCH_POSTS_CLEAR:
      return assign({},
        state,
        {
          [action.subject]: {
            isFetching: false,
            state: 'cleared',
            subject: null,
            response: null,
            error: null,
          }
        }
      );
    default:
      return state;
  }
}
  1. 將結(jié)果放入該subject對應(yīng)下的response,如果錯誤的話將錯誤信息放入error當(dāng)中
  2. isFetching表示當(dāng)前的請求狀態(tài)
  3. 另外還加入了當(dāng)前的狀態(tài)state和subject信息

將請求進(jìn)行封裝

const request = (subject, model, next) => {
  _dispatch(fetchPostsRequest(subject, model, next));
  return true;
};
  1. 寫一個方法來發(fā)起FETCH_POSTS_REQUEST action
  2. 也就是說寫請求的時候不用再管action這東西了,直接調(diào)用request方法

將結(jié)果進(jìn)行封裝

const getResponse = state =>
  state
  && state.response !== null
  && state.response;

const getLoading = (states = []) =>
  states.reduce((pre, cur) =>
    pre || (cur && cur.isFetching)
    , false)
  || false;

  1. 可以獲取結(jié)果和多個請求下loading的狀態(tài)
  2. 有更多的操作或者格式還可以繼續(xù)封裝,比如列表

使用方法redux-request-async-middleware

四、總結(jié)

  1. 使用了redux來進(jìn)行狀態(tài)管理,而并不需要編寫redux那一套復(fù)雜邏輯,最大程度的減少異步操作的復(fù)雜度
  2. 適用于前端通過接口來處理和存儲數(shù)據(jù)的項(xiàng)目
  3. 接口由redux處理,而視圖組件由內(nèi)部state來處理,而外部只暴露簡單的接口來進(jìn)行操作,分離業(yè)務(wù)層和視圖層
  4. 對比react 16.3 new content API,redux的優(yōu)勢在于熱插播的中間件和純函數(shù)reducer寫法

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論