我使用redux-saga并具有以下代码:
function* loginFlow(username, password) {
try {
yield call(loginApi, username, password);
yield put({ type: LOGIN_SUCCESS });
yield put({ type: TOGGLE_LOGGED_DONE, payload: true });
yield put(push('/dashboard'));
} catch (error) {
yield put({ type: LOGIN_ERROR, error });
} finally {
if (yield cancelled()) {
console.log('ALWAYS CANCELLED');
// yield put(replace('/login'));
}
}
}
// Watcher saga.
function* loginWatcher() {
while (true) {
const { username, password } = yield take(LOGIN_REQUESTING);
const task = yield fork(loginFlow, username, password);
const action = yield take([LOGOUT, LOGIN_ERROR]);
if (action.type === LOGOUT) yield cancel(task);
yield call(logoutUser);
}
}
问题在于,loginFlow
函数总是最后被取消(我在控制台中看到'ALWAYS CANCELLED'
)。即使我从const action = yield take([LOGOUT, LOGIN_ERROR]);
中删除了yield call(logoutUser);
和loginWatcher
。
任何想法我的代码有什么问题吗?
请注意,我在index.js的登录页面中使用了withRouter
,上面的传奇故事就出现了(否则我在重定向时会出现黑屏):
const withSaga = injectSaga({ key: 'login', saga });
export default compose( withReducer, withSaga, withConnect, )(LoginPage);
最好的问候
编辑:
如果将loginWatcher
包装在try/catch
中,我也将转到finally
:
function* loginWatcher() {
while (true) {
try {
const { username, password } = yield take(LOGIN_REQUESTING);
const task = yield fork(loginFlow, username, password);
const action = yield take([LOGOUT, LOGIN_ERROR]);
if (action.type === LOGOUT) yield cancel(task);
yield call(logoutUser);
} catch (error) {
yield put({ type: LOGIN_ERROR, error });
} finally {
if (yield cancelled()) {
console.log('HERE AS WELL');
// yield put(push('/login'));
}
}
}
}
答案 0 :(得分:1)
我将发布我们收集的内容作为答案,以便该问题对将来的读者有用。
在redux-saga中,通过call()
和fork()
开始的sagas被递归取消。 Saga 表示可递归取消的任务。因此,当某个传奇被取消后,您应该检查其父传奇,依此类推。
您发布的此代码段:
const withSaga = injectSaga({ key: 'login', saga });
export default compose( withReducer, withSaga, withConnect, )(LoginPage)
Google建议使用this redux-saga + react-boilerplate example。它涵盖取消以及如何禁用它。检查链接以找到有关它的信息。
我不熟悉react-boilerplate(反应生态系统很大),但是我想我的回答至少会缩小搜索范围。如果您感到困惑,请考虑与react-boilerplate提出另一个问题。