使用redux怎么實(shí)現(xiàn)異步操作,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、網(wǎng)絡(luò)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、瑪沁網(wǎng)站維護(hù)、網(wǎng)站推廣。一、redux基礎(chǔ)
redux
通過(guò) dispatch(action) -> 中間件 -> reducer處理數(shù)據(jù) -> 改變store -> 使用subscribe()監(jiān)聽(tīng)store改變更新視圖 的方式管理狀態(tài)
將所有狀態(tài)存儲(chǔ)在一個(gè)store對(duì)象里面
reducer為純函數(shù),而異步操作由于結(jié)果的不確定性所以含有副作用,所以需要特殊處理
react-redux
容器組件,負(fù)責(zé)管理數(shù)據(jù)和業(yè)務(wù)邏輯,不負(fù)責(zé)UI呈現(xiàn)
UI組件,提供UI呈現(xiàn),無(wú)狀態(tài)即不使用this.state,狀態(tài)全部由this.props提供
由connect生成容器組件,每次store改變會(huì)調(diào)用connect,connect接收兩個(gè)參數(shù): mapStateToProps, mapDispatchToProps
mapStateToProps,將狀態(tài)映射到UI組件的props
mapDispatchToProps,將dispatch方法映射到UI組件的props
Provider組件,使用content API將store從頂層開(kāi)始傳到每一層component供connect使用
二、redux處理異步的中間件
redux-thunk
redux-thunk中間件允許action是一個(gè)方法
中間件收到action后會(huì)執(zhí)行action方法并將結(jié)果提供給reducer
action混亂導(dǎo)致不易維護(hù)
redux-saga
saga會(huì)監(jiān)聽(tīng)action并基于這個(gè)action執(zhí)行Effects操作
Effects提供靈活的API,包括阻塞、非阻塞調(diào)用,取消、等待、race等操作
方便隔離并執(zhí)行異步操作,并易于測(cè)試
三、redux-request-async-middleware
先從redux文檔中的異步action說(shuō)起,每個(gè)接口調(diào)用需要dispatch三個(gè)同步action,分別是:
一種通知 reducer 請(qǐng)求開(kāi)始的 action。對(duì)于這種 action,reducer 可能會(huì)切換一下 state 中的 isFetching 標(biāo)記。以此來(lái)告訴 UI 來(lái)顯示加載界面。
一種通知 reducer 請(qǐng)求成功的 action。對(duì)于這種 action,reducer 可能會(huì)把接收到的新數(shù)據(jù)合并到 state 中,并重置 isFetching。UI 則會(huì)隱藏加載界面,并顯示接收到的數(shù)據(jù)。
一種通知 reducer 請(qǐng)求失敗的 action。對(duì)于這種 action,reducer 可能會(huì)重置 isFetching。另外,有些 reducer 會(huì)保存這些失敗信息,并在 UI 里顯示出來(lái)。
也就是一個(gè)接口發(fā)起是這樣的
dispatch(fetchPostsRequest(subject)); fetch(url).then(res => { dispatch(fetchPostsSuccess(subject, res)); }).catch(e => { dispatch(fetchPostsFailure(subject, e)); })
而我做的事情只是將這個(gè)操作封裝進(jìn)中間件里,特殊的地方在于:
所有的異步請(qǐng)求共用這三個(gè)action
用subject來(lái)區(qū)分是哪一個(gè)請(qǐng)求
將所有的結(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 };
和redux-thunk一樣,將方法放進(jìn)action里
中間件攔截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; } }
將結(jié)果放入該subject對(duì)應(yīng)下的response,如果錯(cuò)誤的話將錯(cuò)誤信息放入error當(dāng)中
isFetching表示當(dāng)前的請(qǐng)求狀態(tài)
另外還加入了當(dāng)前的狀態(tài)state和subject信息
將請(qǐng)求進(jìn)行封裝
const request = (subject, model, next) => { _dispatch(fetchPostsRequest(subject, model, next)); return true; };
寫(xiě)一個(gè)方法來(lái)發(fā)起FETCH_POSTS_REQUEST action
也就是說(shuō)寫(xiě)請(qǐng)求的時(shí)候不用再管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;
可以獲取結(jié)果和多個(gè)請(qǐng)求下loading的狀態(tài)
有更多的操作或者格式還可以繼續(xù)封裝,比如列表
使用方法redux-request-async-middleware
四、總結(jié)
使用了redux來(lái)進(jìn)行狀態(tài)管理,而并不需要編寫(xiě)redux那一套復(fù)雜邏輯,大程度的減少異步操作的復(fù)雜度
適用于前端通過(guò)接口來(lái)處理和存儲(chǔ)數(shù)據(jù)的項(xiàng)目
接口由redux處理,而視圖組件由內(nèi)部state來(lái)處理,而外部只暴露簡(jiǎn)單的接口來(lái)進(jìn)行操作,分離業(yè)務(wù)層和視圖層
對(duì)比react 16.3 new content API,redux的優(yōu)勢(shì)在于熱插播的中間件和純函數(shù)reducer寫(xiě)法
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。