[英]retry functionality in redux-saga
在我的应用程序中,我有以下代码
componentWillUpdate(nextProps) {
if(nextProps.posts.request.status === 'failed') {
let timer = null;
timer = setTimeout(() => {
if(this.props.posts.request.timeOut == 1) {
clearTimeout(timer);
this.props.fetchData({
page: this.props.posts.request.page
});
} else {
this.props.decreaseTimeOut();
}
}, 1000);
}
}
它的作用是,当API请求遇到错误时可能是因为没有互联网连接(比如facebook的聊天工作方式),或者后端有错误,它会在5秒后重试,但是setTimeout
需要每隔一秒设置一次以更新商店的一部分,即行this.props.decreaseTimeOut();
,但是如果计数器已经用完,那么五秒钟就会过去, if block
会运行并重新调度fetchData action
。
它运行良好,我没有问题,至少在功能方面,但在代码设计方面,我知道这是一个side-effect
,它不应该在我的react-component中处理,因为我是使用redux-saga(但我是redux-saga的新手,我今天刚刚学会了它),我想把这个功能变成一个传奇,我还不知道如何做到这一点,而且这里fetchData saga
,这是我的fetchData saga
。
import {
take,
call,
put
} from 'redux-saga/effects';
import axios from 'axios';
export default function* fetchData() {
while(true) {
try {
let action = yield take('FETCH_DATA_START');
let response = yield call(axios.get, '/posts/' + action.payload.page);
yield put({ type: 'FETCH_DATA_SUCCESS', items: [...response.data.items] });
} catch(err) {
yield put({ type: 'FETCH_DATA_FAILED', timeOut: 5 });
}
}
}
对代码的侵扰性较小的是使用redux-saga的延迟保证:
catch(err) {
yield put({ type: 'FETCH_DATA_FAILED'});
for (let i = 0; i < 5; i++) {
yield call(delay, 1000);
yield put(/*Action for the timeout/*);
}
}
但我会以这种方式重构你的代码:
function* fetchData(action) {
try {
let response = yield call(axios.get, '/posts/' + action.payload.page);
yield put({ type: 'FETCH_DATA_SUCCESS', items:[...response.data.items] });
} catch(err) {
yield put({ type: 'FETCH_DATA_FAILED'});
yield put({ type: 'SET_TIMEOUT_SAGA', time: 5 });
}
}
}
function *setTimeoutsaga(action) {
yield put({type: 'SET_STATE_TIMEOUT', time: action.time}); // Action that update your state
yield call(delay, 1000);
// Here you use a selector which take the value if is disconnected:
// https://redux-saga.js.org/docs/api/#selectselector-args
const isStillDisconnected = select()
if (isStillDisconnected) {
yield put({type: 'SET_TIMEOUT_SAGA', time: action.time - 1});
}
function *fetchDataWatchers() {
yield takeEvery('FETCH_DATA_START', fetchData);
yield takeEvery('SET_TIMEOUT_SAGA', setTimeoutSaga);
// You can insert here as many watcher you want
}
export default [fetchDataWatchers]; // You will use run saga for registering this collection of watchers
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.