как отменить вложенный запрос с помощью rxjs - PullRequest
1 голос
/ 01 апреля 2019
buttonClicked$.pipe(
switchMap(value=>makeRequest1),
switchMap(responseOfRequest1=>makeRequest2))
.subscribe()

Мне нужно сделать 2 http-запроса последовательно и прервать нисходящий отложенный запрос, если кнопка нажмет.Является ли приведенный выше код правильным подходом?Я понимаю, что новый клик отменит ожидающий request1.если щелчок происходит во время request2, отменяется ли также request2?

Ответы [ 3 ]

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

Это правильное поведение, потому что switchMap отписывается от своего внутреннего Observable, только когда получает next уведомление. Это означает, что если у вас есть два switchMap s, то первый должен излучать первый, чтобы вызвать отмену подписки во втором.

Вы можете избежать этого, используя всего один switchMap и поместив второй makeRequest2 вызов в одну цепочку с makeRequest1.

buttonClicked$.pipe(
  switchMap(value => makeRequest1(value).pipe(
    mergeMap(responseOfRequest1 => makeRequest2(responseOfRequest1)),
  )),
  .subscribe()

Таким образом, когда buttonClicked$ испускает, это делает switchMap отпиской от его внутреннего Observable, которое внутренне отписывается также mergeMap, который отменяет второй вызов, если он все еще ожидает.

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

Почему вторая карта SwitchMap не может быть отменена

Оператор switchMap отменяет свою внутреннюю наблюдаемую только тогда, когда он получает следующее событие от своей восходящей наблюдаемой (т. Е. makeRequest1), а не когда излучает исходная наблюдаемая (то есть buttonClicked$). Итак, рассмотрим следующую последовательность событий:

first button click
first request 1 sent
first response to request 1 received
first request 2 sent
second button click
second request 1 sent
first response to request 2 received
second response to request 1 received

В этом сценарии, поскольку ответ на запрос 2 получен до того, как будет получен второй ответ на запрос 1, хотя второе нажатие кнопки произошло до того, как запрос 2 завершен, запрос 2 никогда не отменялся.

Если запрос 1 отправляет свой второй ответ до того, как запрос 2 получит ответ, то запрос 2 отменяется. Но обратите внимание, что это отменило не само нажатие кнопки, а отмена запроса 1, который отменил его.

Решение

Если вы хотите надежно отменить оба запроса при нажатии кнопки, то оба запроса должны быть выполнены в пределах одного switchMap:

buttonClicked$.pipe(
  switchMap(clickValue => makeRequest1(clickValue).pipe(
    mergeMap(request1Value => makeRequest2(request1Value)))
).subscribe(request2Value => /* ... */);
0 голосов
/ 01 апреля 2019

Да, это работает так с интервалом.Я не проверял его с помощью сетевого запроса.

При каждом щелчке запускается второй наблюдаемый интервал.

const { fromEvent, interval, of } = rxjs;
const { switchMap } = rxjs.operators;

const btn = document.getElementById('btn');
const result = document.getElementById('result');
const click$ = fromEvent(btn, 'click');

click$
	.pipe(
  	switchMap(value => of('Hello')),
  	switchMap(value => interval(1000))
  )
  .subscribe(
  	val => result.innerText = val
  )
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
<button id="btn">Click Me</button>

<div id="result"></div>
...