Redux Saga дает очень медленно при опросе нескольких конечных точек - PullRequest
1 голос
/ 23 апреля 2019

Я опрашиваю два API одновременно, используя redux-saga, и я хочу контролировать оба опроса с помощью 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, происходит несколько секунд, пока все идет дальше (в то время как пользовательский интерфейс также застрял) - чтоможет быть причиной?

1 Ответ

1 голос
/ 24 апреля 2019

Я нашел некоторую закономерность в документах redux-saga, которую можно использовать для решения этого случая, используя cancel вместо race. С его помощью:

отменить текущий эффект, когда задача заблокирована в момент отмена. * * 1006

Я добавил пример (такой же, как я мог бы для вашего кода), который вызывает эффект отмены сразу после запуска действия 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');
        }
    }
}

Проверьте эту ссылку отмену задачи

...