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

redux處理異步action解決方案

 更新時(shí)間:2020年03月22日 09:30:53   作者:karl  
這篇文章主要介紹了redux處理異步action解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

如果沒(méi)有中間件,store.dispatch只能接收一個(gè)普通對(duì)象作為action。在處理異步action時(shí),我們需要在異步回調(diào)或者promise函數(shù)then內(nèi),async函數(shù)await之后dispatch。

dispatch({
  type:'before-load'
})
fetch('http://myapi.com/${userId}').then({
  response =>dispatch({
      type:'load',
      payload:response
    })
})

這樣做確實(shí)可以解決問(wèn)題,特別是在小型項(xiàng)目中,高效,可讀性強(qiáng)。 但缺點(diǎn)是需要在組件中寫(xiě)大量的異步邏輯代碼,不能將異步過(guò)程(例如異步獲取數(shù)據(jù))與dispatch抽象出來(lái)進(jìn)行復(fù)用。而采用類(lèi)似redux-thunk之類(lèi)的中間件可以使得dispatch能夠接收不僅僅是普通對(duì)象作為action。例如:

function load(userId){
  return function(dispatch,getState){
    dispatch({
      type:'before-load'
    })
    fetch('http://myapi.com/${userId}').then({
      response =>dispatch({
        type:'load',
        payload:response
      })
    })
  }  
}
//使用方式
dispatch(load(userId))

使用中間件可以讓你采用自己方便的方式dispatch異步action,下面介紹常見(jiàn)的三種。

1. redux-thunk

function createThunkMiddleware(extraArgument) {
 return ({ dispatch, getState }) => next => action => {
  if (typeof action === 'function') {
   return action(dispatch, getState, extraArgument);
  }

  return next(action);
 };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

2. redux-promise

使用redux-promise可以將action或者action的payload寫(xiě)成promise形式。 源碼:

export default function promiseMiddleware({ dispatch }) {
 return next => action => {
  if (!isFSA(action)) {
   return isPromise(action) ? action.then(dispatch) : next(action);
  }

  return isPromise(action.payload)
   ? action.payload
     .then(result => dispatch({ ...action, payload: result }))
     .catch(error => {
      dispatch({ ...action, payload: error, error: true });
      return Promise.reject(error);
     })
   : next(action);
 };
}

3. Redux-saga

redux-saga 是一個(gè)用于管理應(yīng)用程序 Side Effect(副作用,例如異步獲取數(shù)據(jù),訪問(wèn)瀏覽器緩存等)的 library,它的目標(biāo)是讓副作用管理更容易,執(zhí)行更高效,測(cè)試更簡(jiǎn)單,在處理故障時(shí)更容易

3.1 基本使用

import { call, put, takeEvery, takeLatest} from 'redux-saga/effects';

//復(fù)雜的異步流程操作
function* fetchUser(action){
 try{
  const user = yield call(API.fetchUser, action.payload);
  yield put({type:"USER_FETCH_SUCCEEDED",user:user})
 }catch(e){
  yield put({type:"USER_FETCH_FAILED",message:e.message})
 }
}

//監(jiān)聽(tīng)dispatch,調(diào)用相應(yīng)函數(shù)進(jìn)行處理
function* mainSaga(){
 yield takeEvery("USER_FETCH_REQUESTED",fetchUser);
}

//在store中注入saga中間件
import {createStore,applyMiddleware} from 'redux';
import createSagaMiddleware from 'redux-saga';

import reducer from './reducers';
import mainSaga from './mainSaga';
const sagaMiddleware = createSagaMiddleware();

const store = createStore(reducer,initalState,applyMiddleware(sagaMiddleware));

sagaMiddleware.run(mainSaga)

3.2 聲明式effects,便于測(cè)試

為了測(cè)試方便,在generator中不立即執(zhí)行異步調(diào)用,而是使用call、apply等effects創(chuàng)建一條描述函數(shù)調(diào)用的對(duì)象,saga中間件確保執(zhí)行函數(shù)調(diào)用并在響應(yīng)被resolve時(shí)恢復(fù)generator。

function* fetchProducts() {
 const products = yield Api.fetch('/products')
 dispatch({ type: 'PRODUCTS_RECEIVED', products })
}

//便于測(cè)試
function* fetchProducts() {
 const products = yield call(Api.fetch, '/products')
 //便于測(cè)試dispatch
 yield put({ type: 'PRODUCTS_RECEIVED', products })
 // ...
}
// Effect -> 調(diào)用 Api.fetch 函數(shù)并傳遞 `./products` 作為參數(shù)
{
 CALL: {
  fn: Api.fetch,
  args: ['./products'] 
 }
}

3.3 構(gòu)建復(fù)雜的控制流

saga可以通過(guò)使用effect創(chuàng)建器、effect組合器、saga輔助函數(shù)來(lái)構(gòu)建復(fù)雜的控制流。

effect創(chuàng)建器:

  • take:阻塞性effect,等待store中匹配的action或channel中的特定消息。
  • put:非阻塞性effect,用來(lái)命令 middleware 向 Store 發(fā)起一個(gè) action。
  • call:阻塞性effect,用來(lái)命令 middleware 以參數(shù) args 調(diào)用函數(shù) fn。
  • fork:非阻塞性effect,用來(lái)命令 middleware 以 非阻塞調(diào)用 的形式執(zhí)行 fn
  • select:非阻塞性effect,用來(lái)命令 middleware 在當(dāng)前 Store 的 state 上調(diào)用指定的選擇器

effect組合器:

race:阻塞性effect:用來(lái)命令 middleware 在多個(gè) Effect 間運(yùn)行 競(jìng)賽(Race)

function fetchUsersSaga { 
 const { response, cancel } = yield race({ 
 response: call(fetchUsers), 
 cancel: take(CANCEL_FETCH) 
 }) 
}

all: 當(dāng) array 或 object 中有阻塞型 effect 的時(shí)候阻塞,用來(lái)命令 middleware 并行地運(yùn)行多個(gè) Effect,并等待它們?nèi)客瓿?/p>

function* mySaga() { 
 const [customers, products] = yield all([ 
 call(fetchCustomers), 
 call(fetchProducts) 
 ]) 
}

effect輔助函數(shù):

takeEvery:非阻塞性effect,在發(fā)起(dispatch)到 Store 并且匹配 pattern 的每一個(gè) action 上派生一個(gè) saga

const takeEvery = (patternOrChannel, saga, ...args) => fork(function*() { 
while (true) { 
const action = yield take(patternOrChannel) 
yield fork(saga, ...args.concat(action)) 
} 
  })

takeLatest:非阻塞性,在發(fā)起到 Store 并且匹配 pattern 的每一個(gè) action 上派生一個(gè) saga。并自動(dòng)取消之前所有已經(jīng)啟動(dòng)但仍在執(zhí)行中的 saga 任務(wù)。

 const takeLatest = (patternOrChannel, saga, ...args) => fork(function*() { 
  let lastTask 
  while (true) { 
  const action = yield take(patternOrChannel) 
  if (lastTask) { 
  yield cancel(lastTask) // 如果任務(wù)已經(jīng)結(jié)束,cancel 則是空操作 
  } 
  lastTask = yield fork(saga, ...args.concat(action)) 
  } 
 })

throttle:非阻塞性,在 ms 毫秒內(nèi)將暫停派生新的任務(wù)

const throttle = (ms, pattern, task, ...args) => fork(function*() { 
  const throttleChannel = yield actionChannel(pattern) 
  ​ 
  while (true) { 
  const action = yield take(throttleChannel) 
  yield fork(task, ...args, action) 
  yield delay(ms) 
  } 
  })

到此這篇關(guān)于redux處理異步action解決方案的文章就介紹到這了,更多相關(guān)redux 異步action內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論