配方
- action: redoable
- effects: put, take, takeEvery
流程
- 点击按钮,执行sayHello的action
- sayHello的action只有执行第3次的时候才会成功
- 如果sayHello失败则自动重试直到成功或到达重试次数
实现
1 先定义一个redoable的action creator
/**
* @params action: 需要被重试的标准action
* @params successType: 当action成功后会被dispatch的action type
* @params failureType: 当action失败后会被dispatch的action type
* @params time: 重试最大次数
*/
function redoable(action, successType, failureType, time = 1) {
return {
type: 'REDOABLE',
payload: {
successType,
failureType,
action,
time
}
};
}
2 点击按钮时dispatch一个REDOABLE的SAY_HELLO的action
function Hello({
handleSayHello
}) {
return (
<div>
<button onClick={handleSayHello}>Say Hello</button>
</div>
);
}
Hello = connect(
() => ({}),
(dispatch) => ({
handleSayHello() {
dispatch(redoable({
type: 'SAY_HELLO'
}, 'SAY_HELLO_SUCCESS', 'SAY_HELLO_FAILURE', 3));
}
})
)(Hello);
3 实现sayHello的saga来处理SAY_HELLO的action
function* sayHello(action) {
times++;
if (times < 3) {
yield put({
type: 'SAY_HELLO_FAILURE'
});
return;
}
times = 0;
alert('Hello, nice to meet you!');
yield put({
type: 'SAY_HELLO_SUCCESS'
});
}
4 实现redoableInvoke的saga来处理REDOABLE的action
function* redoableInvoke(action) {
const {
action: realAction,
successType,
failureType,
time
} = action.payload;
yield put(realAction);
const {type} = yield take([successType, failureType]);
if (type === failureType) {
if (time === 0) {
return;
}
const nextAction = {...action};
nextAction.payload = {...nextAction.payload, time: time - 1};
yield put(nextAction);
}
}
5 使用takeEvery来运行两个saga
store.runSaga(function * () {
yield takeEvery('REDOABLE', redoableInvoke);
yield takeEvery('SAY_HELLO', sayHello);
});
height="265" width="100%" scrolling="no" title="Redux Saga Cookbook 02" src="//codepen.io/awaw00/embed/BppVgJ/?height=265&theme-id=0&default-tab=js,result&embed-version=2" allowfullscreen="true">See the Pen <a href="http://codepen.io/awaw00/pen/BppVgJ/">Redux Saga Cookbook 02</a> by aaron wang (<a href="http://codepen.io/awaw00">@awaw00</a>) on <a href="http://codepen.io">CodePen</a>.