說明:對Redux不瞭解的同窗可先看看這篇文章Redux技術架構簡介(一)html
這裏說的Redux異步實現,是專指Redux中的異步Action實現,而不是指應用的異步實現,由於Redux自己只支持同步action,即發送action,state當即更新;那若是我在發送一個action後,須要state過一段時間再更新呢?按正常的思路redux是沒法處理這種狀況的,下面就來看看異步Action是如何實現的吧!react
須要提的一點是,其實徹底能夠將異步邏輯寫在View中,而後在回調函數中發送action。可是若是你要配合react一塊兒使用,這樣作就違背了react-redux的設計思想,即UI與邏輯的分離(具體的實現能夠在下一篇文章中看到),並且當存在多個異步請求時也很難將異步邏輯抽象出來,因此異步邏輯應該由Redux架構實現,這樣也就必須實現發送異步action了
爲了解決上面提到的問題,咱們須要引入中間件的概念。npm
中間件執行的時機是在action發起以後,reducer執行以前。json
即在dispatch一個action以後,通過一系列的中間件處理過程,再進行reducer。redux
本質上,中間件就是對dispatch函數的改造。當執行dispatch(action)時,會先調用中間件,進行一些內部邏輯處理,如:添加日誌等,以後再執行dispatch。若是要支持中間件的鏈式調用,必須再返回一個dispatch。
下面是中間件的簡單實現:segmentfault
function logger(store) { // 這裏的 next 必須指向前一個 middleware 返回的函數: const next = store.dispatch return function dispatchAndLog(action) { console.log('dispatching', action) let result = next(action) console.log('next state', store.getState()) return result } }
可使用Redux的API—applyMiddleware直接使用中間件,代碼以下:架構
import {applyMiddleware,createStore} from 'redux'; import {createLogger} from 'redux-logger';//log中間件 import thunk from 'redux-thunk';//將dispatch改形成能夠接受函數做爲參數的中間件 import indexPhotomainReducer from '../reducer/indexPhotomainReducer'; const logger = createLogger(); const store = createStore( indexPhotomainReducer, applyMiddleware(thunk, logger) );
因而可知,能夠把applyMiddleware做爲createStore的第二個參數傳入,你所使用的中間件須要下載單獨npm包,而後按順序傳入applyMiddleware函數中(注:中間件有順序要求,須要看下每一箇中間件的使用文檔,logger通常要放在最後)。app
須要增長三種action異步
示例代碼以下:ide
export const requestPostsAction = () => { return { type: REQUEST_POSTS }; } export const receivePostsSuccessAction = (data) => { return { type: RECEIVE_POSTS_SUCCESS, data }; } export const receivePostsFailureAction = (error) => { return { type: RECEIVE_POSTS_FAILURE, error }; }
返回參數徹底能夠自定義。這3種action分別在請求開始前,請求成功後,請求失敗後發送。
## (2) State設計
爲了配合異步Action,能夠在state樹中增長2個屬性:
State屬性能夠憑本身喜愛隨意設計。設計好後能夠這樣編寫reducer:
let sliderReducer = function (state = initialState, action) { switch(action.type){ case photomainAction.RECEIVE_POSTS_SUCCESS: return Object.assign({}, state, {photoData,videoData,isFetching:false,isValidate:true}); case photomainAction.RECEIVE_POSTS_FAILURE: return Object.assign({}, state, {isFetching:false,isValidate:false}); case photomainAction.REQUEST_POSTS: return Object.assign({}, state, {isFetching:true,isValidate:false}); default: return state; } }
當設計好action和state後,咱們想要達到的效果是--能夠像同步同樣dispatch一個action,而不用考慮異步邏輯。
爲了達到這種效果,首先面臨的問題是,異步邏輯放在哪裏?這裏只有2個選擇:action中或reducer中(store是不適合處理數據的)。因爲reducer必須是一個純函數,他不適合處理像異步請求這樣存在不肯定的輸出的邏輯。最後只能放在action中處理了。
這時,爲了處理異步請求,action建立函數須要返回一個帶有異步請求邏輯的函數,而不是一個對象了。而dispatch只能接受對象,不能接受函數做爲參數,這樣就面臨又一個問題:如何讓dispatch接受函數?
接下來就是redux-thunk中間件發揮做用的時候了,他可讓dispatch接受一個函數(原理就是上一節講的,他實際上是改寫了dispatch函數),最終異步的action能夠這樣實現:
//定義一個action creator – fetchPosts export const fetchPosts = () => (dispatch, getState) => { dispatch(requestPostsAction()); return window.fetch("/photo/initPage").then(response=>{ if(response.ok){ return response.json(); }else{ dispatch(receivePostsFailureAction("error")); } }).then(data => { if(data){ dispatch(receivePostsSuccessAction(data)); }else{ dispatch(receivePostsFailureAction("error")); } }); }
這樣就能夠像同步同樣發送action了,即:
dispatch(fetchPosts());
接下來只需靜靜等待view的更新就好了,這樣就實現了整個Redux的異步流程。
本篇到此告一段落,下一篇介紹React與Redux整合技術。