申明:對Redux不相識的同硯可先看看這篇文章Redux手藝架構簡介(一)
媒介
這裏說的Redux異步完成,是專指Redux中的異步Action完成,而不是指運用的異步完成,因為Redux自身只支撐同步action,即發送action,state馬上更新;那假如我在發送一個action后,須要state過一段時間再更新呢?按平常的思緒redux是沒法處置懲罰這類狀況的,下面就來看看異步Action是怎樣完成的吧!
須要提的一點是,實在完全能夠將異步邏輯寫在View中,然後在回調函數中發送action。然則假如你要合營react一同運用,如許做就違犯了react-redux的設想頭腦,即UI與邏輯的星散(詳細的完成能夠鄙人一篇文章中看到),而且當存在多個異步請求時也很難將異步邏輯籠統出來,所以異步邏輯應該由Redux架構完成,如許也就必需完成發送異步action了
1. 中間件(Middleware)
為相識決上面提到的題目,我們須要引入中間件的觀點。
(1)機遇
中間件實行的機遇是在action提議以後,reducer實行之前。
即在dispatch一個action以後,經由一系列的中間件處置懲罰歷程,再舉行reducer。
(2)道理
本質上,中間件就是對dispatch函數的革新。當實行dispatch(action)時,會先挪用中間件,舉行一些內部邏輯處置懲罰,如:增添日記等,以後再實行dispatch。假如要支撐中間件的鏈式挪用,必需再返回一個dispatch。
下面是中間件的簡樸完成:
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
}
}
(3) 在Redux中運用中間件
能夠運用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平常要放在末了)。
2. Redux異步完成
(1) Action設想
須要增添三種action
- 關照異步請求提議的action
- 異步請求勝利的action
- 異步請求失利的action
示例代碼以下:
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個屬性:
- isFetching:示意是不是正在處置懲罰異步請求。
- isValidate:示意數據的有效性,他的作用是在異步請求發送失利后,通知View當前state的數據是過期的數據。
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;
}
}
(3) redux-thunk中間件
當設想好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整合手藝。