小編給大家分享一下redux處理異步action的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
為鳳翔等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及鳳翔網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、鳳翔網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
如果沒有中間件,store.dispatch只能接收一個(gè)普通對象作為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í)可以解決問題,特別是在小型項(xiàng)目中,高效,可讀性強(qiáng)。 但缺點(diǎn)是需要在組件中寫大量的異步邏輯代碼,不能將異步過程(例如異步獲取數(shù)據(jù))與dispatch抽象出來進(jìn)行復(fù)用。而采用類似redux-thunk之類的中間件可以使得dispatch能夠接收不僅僅是普通對象作為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,下面介紹常見的三種。
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寫成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ù),訪問瀏覽器緩存等)的 library,它的目標(biāo)是讓副作用管理更容易,執(zhí)行更高效,測試更簡單,在處理故障時(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)聽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,便于測試
為了測試方便,在generator中不立即執(zhí)行異步調(diào)用,而是使用call、apply等effects創(chuàng)建一條描述函數(shù)調(diào)用的對象,saga中間件確保執(zhí)行函數(shù)調(diào)用并在響應(yīng)被resolve時(shí)恢復(fù)generator。
function* fetchProducts() { const products = yield Api.fetch('/products') dispatch({ type: 'PRODUCTS_RECEIVED', products }) } //便于測試 function* fetchProducts() { const products = yield call(Api.fetch, '/products') //便于測試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可以通過使用effect創(chuàng)建器、effect組合器、saga輔助函數(shù)來構(gòu)建復(fù)雜的控制流。
effect創(chuàng)建器:
take:阻塞性effect,等待store中匹配的action或channel中的特定消息。
put:非阻塞性effect,用來命令 middleware 向 Store 發(fā)起一個(gè) action。
call:阻塞性effect,用來命令 middleware 以參數(shù) args 調(diào)用函數(shù) fn。
fork:非阻塞性effect,用來命令 middleware 以 非阻塞調(diào)用 的形式執(zhí)行 fn
select:非阻塞性effect,用來命令 middleware 在當(dāng)前 Store 的 state 上調(diào)用指定的選擇器
effect組合器:
race:阻塞性effect:用來命令 middleware 在多個(gè) Effect 間運(yùn)行 競賽(Race)
function fetchUsersSaga { const { response, cancel } = yield race({ response: call(fetchUsers), cancel: take(CANCEL_FETCH) }) }
all: 當(dāng) array 或 object 中有阻塞型 effect 的時(shí)候阻塞,用來命令 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。并自動取消之前所有已經(jī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) } })
看完了這篇文章,相信你對“redux處理異步action的示例分析”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
標(biāo)題名稱:redux處理異步action的示例分析
當(dāng)前URL:http://jinyejixie.com/article6/joodig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號、品牌網(wǎng)站制作、網(wǎng)站導(dǎo)航、外貿(mào)網(wǎng)站建設(shè)、虛擬主機(jī)、手機(jī)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)