Функция Redux Saga выдает результаты очень медленно при опросе нескольких конечных точек

#redux-saga

#redux-saga

Вопрос:

Я одновременно опрашиваю два 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:

Я нашел некоторый шаблон в документах 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');
        }
    }
}

  

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

Комментарии:

1. Спасибо, это решение красивее, решает мою проблему (что, по-видимому, произошло только при открытии devtools)