【问题标题】:How to call redux saga watcher recursively如何递归调用 redux saga watcher
【发布时间】:2019-01-12 12:27:02
【问题描述】:
我正在努力递归调用 redux-saga 观察者,它与 setInterval 函数的工作方式相同,其中观察者函数应该在每 n 秒后调用一次,我们可以像 clearInterval 一样清除间隔。
我的要求 -
每 n 秒后递归调用 redux-saga watcher。这里 n 存储在 store 中,并且可以更新。因此,当 n 将在 store 中更新时,我们需要停止旧的 watcher 函数(如 clearInterval)并以更新的 n 秒重新启动旧的递归 watcher。
【问题讨论】:
标签:
react-redux
redux-saga
【解决方案1】:
import { delay } from "redux-saga";
import {
all,
take,
select,
cancel,
put,
takeEvery,
fork,
} from "redux-saga/effects";
export function* loop() {
// Get the store
const state = yield select();
let n = state.n;
// Will keep looping with a delay of n milliseconds,
// where n is accessed from the store.
while (true) {
yield delay(n);
yield put({ type: "CALLED_AGAIN" });
}
}
export function* startProcess() {
// Start the loop
let task = yield fork(loop);
let action = yield take(["END_PROCESS", "INC_TIMER"]);
switch (action.type) {
case "END_PROCESS":
// For stopping the loop
yield cancel(task);
break;
case "INC_TIMER":
// While changing the duration of the timer:
// 1) End the previous loop
yield cancel(task);
// 2) Change the timer(stored as n here)
yield put({ type: "INC_TIMER_COMPLETED" });
// 3) Start the recursive calls again
yield put({ type: "START_PROCESS" });
break;
default:
break;
}
}
export function* watchStartTasks() {
// Initially "START_PROCESS" is dispatched to start the recursive calls.
yield takeEvery("START_PROCESS", startProcess);
}
export default function* rootSaga() {
yield all([watchStartTasks()]);
}
【解决方案2】:
答案会根据某些标准而改变——比如你是想在 N 改变后等待 N 毫秒,还是在明确的情况下你想取消工人——但这可能会给你一个粗略的想法:
function * rootSaga() {
let prevTask
yield takeEvery(CHANGE_N, function*() {
if (prevTask) prevTask.cancel();
const n = yield select(getN);
task = yield throttle(n, FOO, fooSaga);
});
}
如果throttle 不够用,您可能需要使用delay 和fork 将其替换为自定义观察程序。