本文目標:但願經過買進口水果生鮮的例子,和你們探討一下如何處理異步的
async action
。node
在上一篇文章 Redux入門 -- 拆分 reducer 中,阿大經過 redux
的 bindReducers
方法將水果店的業務分治成功,店鋪也越作越大。以致於有顧客開始想要買一些進口的水果生鮮。git
阿大考慮了一下,決定繼續拓展這個店鋪,從事進口商品的銷售。首先是顧客的需求行爲須要購買進口水果生鮮:github
// 買水果 - 進口蘋果
+ function buyImportedApple(num) {
+ return {
+ type: 'BUY_IMPORTED_APPLE',
+ payload: {
+ num
+ }
+ }
+ }
// 買生鮮 - 進口雞蛋
+ function buyImportedEgg(num) {
+ return {
+ type: 'BUY_IMPORTED_EGG',
+ payload: {
+ num
+ }
+ }
+ }
複製代碼
而後水果部和生鮮部的帳本也要更新啦:redux
// 水果帳本
const fruitState = {
orange: 0,
apple: 0,
banana: 0,
+ importedApple: 0
};
// 生鮮帳本
const freshState = {
egg: 0,
fish: 0,
vegetable: 0,
+ importedEgg: 0
};
複製代碼
一樣的,相應部門的收銀員們也要學會怎麼處理進口水果生鮮的記帳,他們的記帳方式要改爲下面這樣:app
// 水果部收銀員
function fruitReducer(state = fruitState, action) {
// 若是有人買了相應的水果,更新帳本
switch (action.type) {
case 'BUY_APPLE':
return Object.assign({}, state, {
apple: state.apple + action.payload.count
});
case 'BUY_IMPORTED_APPLE':
return Object.assign({}, state, {
importedApple: state.importedApple + action.payload.count
});
// 買其餘的東西,不更新帳本,原樣返回
default: return state;
}
}
// 生鮮部收銀員
function freshReducer(state = freshState, action) {
switch (action.type) {
case 'BUY_EGG':
return Object.assign({}, state, {
egg: state.egg + action.payload.count
});
case 'BUY_IMPORTED_EGG':
return Object.assign({}, state, {
importedEgg: state.importedEgg + action.payload.count
});
default: return state;
}
}
複製代碼
但是這時候阿大發現,進口水果生鮮不能大量存在本身倉庫賣,由於它們又貴又容易壞,只有當顧客須要買的時候,才能去採購這些水果生鮮,因而阿大又僱了一個採購員專門負責處理要買進口水果和生鮮的顧客,等到貨了再通知銷售員取貨給顧客:異步
// 採購商品生成器,不一樣的商品須要不一樣的時間採購
function fetchGoodsGenerator(time, action) {
// 用延時模擬採購時間
const timer = setTimeout(() => {
clearTimeout(timer);
// 採購完成,通知銷售員
store.dispatch(action);
}, time);
}
// 採購進口蘋果須要 2 天(2s)
function fetchImportedApple(action) {
fetchGoodsGenerator(2000, action);
}
// 採購進口雞蛋須要 3 天(3s)
function fetchImportedEgg(action) {
fetchGoodsGenerator(3000, action);
}
// 採購員
const API = {
fetchImportedApple, // 採購進口蘋果
fetchImportedEgg // 採購進口雞蛋
}
複製代碼
好了,佈置完了以後,顧客開始來買水果生鮮了:async
// 銷售員開始銷售,採購員開始採購
store.dispatch(buyApple(3));
API.fetchImportedApple(buyImportedApple(10));
store.dispatch(buyEgg(1));
API.fetchImportedEgg(buyImportedEgg(10));
store.dispatch(buyApple(4));
API.fetchImportedApple(buyImportedApple(10));
store.dispatch(buyEgg(8));
API.fetchImportedEgg(buyImportedEgg(10));
// {"fruit":{"apple":3,"importedApple":0},"fresh":{"egg":0,"importedEgg":0}}
// {"fruit":{"apple":3,"importedApple":0},"fresh":{"egg":1,"importedEgg":0}}
// {"fruit":{"apple":7,"importedApple":0},"fresh":{"egg":1,"importedEgg":0}}
// {"fruit":{"apple":7,"importedApple":0},"fresh":{"egg":9,"importedEgg":0}}
// {"fruit":{"apple":7,"importedApple":10},"fresh":{"egg":9,"importedEgg":0}}
// {"fruit":{"apple":7,"importedApple":20},"fresh":{"egg":9,"importedEgg":0}}
// {"fruit":{"apple":7,"importedApple":20},"fresh":{"egg":9,"importedEgg":10}}
// {"fruit":{"apple":7,"importedApple":20},"fresh":{"egg":9,"importedEgg":20}}
複製代碼
如今水果生鮮店的進口業務也穩妥了,阿大內心美滋滋~函數
在實際的開發當中咱們常常會調用一些 API 接口獲取數據更新 state。剛開始使用 redux 的一個誤區就是在 reducer 裏接收到異步的 action 以後,就在 reducer 裏作異步操做,調用 API。可是這樣是錯誤的。reducer 只能是純函數,不能有任何反作用。這樣才能保證對於相同的輸入,必定會有相同的輸出。post
代碼地址:Redux 入門 -- 處理 async action,直接控制檯運行
node ./demo3/index.js
查看效果fetch