Redux-thunk
import axios from 'axios';
import {
ISLOADING,
ERRORS,
GETDATA
}from '../constants/actionTypes'
let request = (type, params) => {return {type, params}}
let receive = (type, data) => {return {type, data}}
export function getList(params){
return async dispatch => {
dispatch(request(ISLOADING,params))
try {
let res = await axios.post('localhost:8080/getdatas',params)
dispatch(receive(GETDATA,{payload:res})
}catch (err){
dispatch(receive(ERRORS, {status: 2, errmsg: '數(shù)據(jù)錯(cuò)誤'}))
}
}
}
上面代碼中,getList是一個(gè)Action Creator(動(dòng)作生成器),返回一個(gè)函數(shù)。這個(gè)函數(shù)執(zhí)行后,先發(fā)出一個(gè)Action(request(ISLOADING,params)),然后進(jìn)行異步操作。拿到結(jié)果后,然后再發(fā)出一個(gè) Action(receive(GETDATA,{payload:res})。
getList返回了一個(gè)函數(shù),而普通的 Action Creator 默認(rèn)返回一個(gè)對(duì)象。
使用Redux-thunk
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducers';
const store = createStore(
reducer,
applyMiddleware(thunk)
);
上面代碼使用redux-thunk中間件,改造store.dispatch,使得后者可以接受函數(shù)作為參數(shù)。
使用redux-thunk的最大問題就是太復(fù)雜了,重復(fù)的模板代碼太多。
redux-promise
由于redux-thunk寫起來實(shí)在是太麻煩了,redux-promise出現(xiàn)了,
它自定義了一個(gè)middleware,當(dāng)檢測到有action的payload屬性是Promise對(duì)象時(shí),就會(huì):
若resolve,觸發(fā)一個(gè)此action的拷貝,但payload為promise的value,并設(shè)status屬性為”success”
若reject,觸發(fā)一個(gè)此action的拷貝,但payload為promise的reason,并設(shè)status屬性為”error”
import axios from 'axios';
import {
GETDATA
} from '../constants/actionTypes'
let request = (type, params) => {return {type, params}}
let receive = (type, data) => {return {type, data}}
export function getList(params){
return {
type: GETDATA,
payload: axios.post(url,params)
}
}
代碼量明顯減少。
redux-promise雖然在代碼量上減少,但是,它太過精簡了,結(jié)果我們不能在拿到數(shù)據(jù)前,做任何操作。
使用redux-thunk,在請(qǐng)求數(shù)據(jù)前,先發(fā)一個(gè)action,我們可以根據(jù)這個(gè)action做出操作,但是promise卻不行。
最初觸發(fā)的action被中間件攔截然后過濾掉了。原因很簡單,redux認(rèn)可的action對(duì)象是簡單對(duì)象,而在redux-promise中,初始action的payload是個(gè)Promise。
redux-promise-middleware
redux-promise-middleware相比redux-promise,采取了更為溫和和漸進(jìn)式的思路,保留了和redux-thunk類似的三個(gè)action。
import axios from 'axios';
import {
GETDATA
} from '../constants/actionTypes'
let request = (type, params) => {return {type, params}}
let receive = (type, data) => {return {type, data}}
export function getList(params){
return {
type: GETDATA,
payload: {
promise: axios.post(url,params)
}
}
}
reduces:
const reducer = function(state, action) {
switch(action.type) {
case GET_DATA_PENDING :
return state;
case GET_DATA_FULFILLED :
return {
...state,
isInitialized: true
};
case GET_DATA_REJECTED :
return {
...state,
isInitialized: false
};
}
}
redux-promise-middleware,為action提供了三個(gè)type,_PENDING、_FULFILLED、_REJECTED,代表了不同狀態(tài)。
它的遺憾則是只在action層實(shí)現(xiàn)了簡化,對(duì)reducer層則束手無策。另外,相比redux-thunk,它還多出了一個(gè)_PENDING的字符串模板代碼(三個(gè)action卻需要四個(gè)type)。