轮询多个端点时,Redux Saga 的产出非常缓慢
Redux Saga yields very slowly when polling multiple endpoints
我正在使用 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 也卡住)- 可能是什么原因?
我在 redux-saga 文档中发现了一些模式,您可以使用这些模式通过使用 cancel
而不是 race
来解决这种情况。使用它将:
cancel the current Effect where the task is blocked at the moment of
cancellation.
我添加了一个示例(尽可能与您的代码相同),在触发 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
将取消向下传播到任何子任务。
If the callee is still pending and the caller decides to cancel
the operation, it triggers a kind of a signal that propagates down to
the callee (and possibly to any deep operations called by the callee
itself). All deeply pending operations will be cancelled.
export function* pollEventsSagaWorker() {
try {
while (true) {
yield put(fetchEvents());
yield delay(EVENT_POLL_INTERVAL);
}
} finally {
if (yield cancelled()) {
console.error('polling stopped');
}
}
}
检查此引用 task-cancellation
我正在使用 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 也卡住)- 可能是什么原因?
我在 redux-saga 文档中发现了一些模式,您可以使用这些模式通过使用 cancel
而不是 race
来解决这种情况。使用它将:
cancel the current Effect where the task is blocked at the moment of cancellation.
我添加了一个示例(尽可能与您的代码相同),在触发 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
将取消向下传播到任何子任务。
If the callee is still pending and the caller decides to cancel the operation, it triggers a kind of a signal that propagates down to the callee (and possibly to any deep operations called by the callee itself). All deeply pending operations will be cancelled.
export function* pollEventsSagaWorker() {
try {
while (true) {
yield put(fetchEvents());
yield delay(EVENT_POLL_INTERVAL);
}
} finally {
if (yield cancelled()) {
console.error('polling stopped');
}
}
}
检查此引用 task-cancellation