我正在使用redux-saga同时轮询两个API,并且希望通过race
来控制两个轮询,并且可以同时停止这两个轮询:
function* root() {
yield all([
call(startSimulation),
takeEvery(RESTART_SIMULATION, stopAndStartSimulation),
takeEvery(STOP_SIMULATION, haltSimulation),
])
export function* startPolling(vin: string) {
yield all([call(pollEventsSagaWorker), call(pollStatusSagaWorker, vin)])
}
export function* initiateSimulation() {
const vin = yield select(vinSelector)
yield call(startPolling, vin)
}
export function* haltSimulation() {
const runningSimulation = yield select(simulationsDataSelector)
if (runningSimulation) {
yield put(deleteSimulation(runningSimulation.id))
}
}
export function* startSimulation() {
while (true) {
yield take(INIT_SIMULATION)
yield race([call(initiateSimulation), take(STOP_SIMULATION)])
}
}
export function* stopAndStartSimulation() {
yield put(stopSimulation())
// do some other stuff
}
stopSimulation()
是动作创建者(类型为STOP_SIMULATION
)。
以下是轮询传奇的一个示例:
export function* pollEventsSagaWorker() {
while (true) {
try {
yield put(fetchEvents())
yield delay(EVENT_POLL_INTERVAL)
} catch (err) {
console.error('polling failed', err)
}
}
}
问题是,当我打电话给STOP_SIMULATION
时,需要花几秒钟的时间才能继续进行(同时UI也被卡住了)-可能是什么原因?
答案 0 :(得分:1)
我在redux-saga文档中找到了一些模式,可以通过使用cancel
而不是race
来解决这种情况。使用它将:
取消当前的效果,该效果在以下时间被阻止 取消。
我添加了一个示例(与您的代码相同),可以在触发STOP_SIMULATION
动作后立即触发取消效果。
// THE CONTROL LOOP
export function* mainSaga() {
while (yield take(INIT_SIMULATION)) {
// starts the task in the background
const task = yield fork(pollEventsSagaWorker);
// wait for the user stop action
yield take(STOP_SIMULATION);
// user clicked stop.
// cancel the polling by causing the forked saga to enter its finally block
yield cancel(task);
}
}
这将导致pollEventsSagaWorker
将取消信息向下传播到所有子任务。
如果被叫方仍在等待中,而主叫方决定取消 该操作会触发一种信号,该信号向下传播到 被调用方(可能还会执行被调用方调用的任何深层操作 本身)。所有待处理的操作都将被取消。
export function* pollEventsSagaWorker() {
try {
while (true) {
yield put(fetchEvents());
yield delay(EVENT_POLL_INTERVAL);
}
} finally {
if (yield cancelled()) {
console.error('polling stopped');
}
}
}
检查此推荐人task-cancellation