Отмена запросов через сагу - PullRequest
0 голосов
/ 28 апреля 2018

Мы предоставляем опцию раскрывающегося списка вверху. Допустим, есть варианты A B C. Всякий раз, когда пользователь изменяет опцию выпадающего меню, запускается сага, которая совершает около 10 различных вызовов webapi (карта вызовов, которые выполняются параллельно)

Мы используем хелпер takeLatest в саге watcher. Таким образом, если пользователь немедленно меняет раскрывающийся список с A на B., Только клиентские вызовы, сделанные через B, потребляются на стороне клиента как сага takeLatest о прерываниях, которая была вызвана A.

Теперь проблема заключается в том, что, хотя потребляются только вызовы B, все ожидающие вызовы A, находящиеся в состоянии ожидания, также выполняются до завершения. Только сага (из-за A) прерывается, но не вызовы API. Мы можем видеть это на вкладке сети. Таким образом, если пользователь переключается между A B C довольно быстро, у нас будет около 30-40 вызовов на сервер. Все они выполняются до конца, хотя мы просто заинтересованы в завершении последних 10 звонков. Если мы видим в инструментах chrome dev, последние 10 вызовов находятся в очереди или останавливаются, пока не будут выполнены вышеуказанные. Разве нет способа распространять отмену из саги (уровень takeLatest) на аксиомы и отменять обещания. Документы Axios говорят об отмене и токенах, но я не совсем понимаю, как распространять отмену в среде Redx-Saga и Axios. Как инициировать отмену из саги в axios?

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Если кто-то заинтересован в рабочем решении этой конкретной проблемы, я являюсь создателем аддона библиотеки Redux Saga специально для подобных проблем - https://github.com/klis87/redux-saga-requests

Он делает такие вещи автоматически для вас - если сага отменена, запрос отменяется автоматически, поэтому вам даже не нужно об этом думать.

0 голосов
/ 29 апреля 2018
const cancelSource = axios.CancelToken.source()
try {
  yield all([
    call(axios.get, "/api/1", { cancelToken: cancelSource.token }),
    call(axios.get, "/api/2", { cancelToken: cancelSource.token }),
    /// ...
  ])
} finally {
  if (yield cancelled()) {
    yield call(cancelSource, cancelSource.cancel)
  }
}
...