Есть ли способ подписаться только на последний ответ SwitchMap? - PullRequest
1 голос
/ 06 ноября 2019

Рассмотрим следующий пример:


import { fromEvent } from 'rxjs'; 
import { switchMap, tap } from 'rxjs/operators';
import { ajax } from 'rxjs/ajax';

const httpCall$ = ajax.getJSON('https://rickandmortyapi.com/api/character/');
const click$ = fromEvent(document, 'click');

const switchMapExample$ = click$.pipe(
  tap(() => console.log('inside switchMap - click happend')),
  switchMap(() => {
    console.log('inside switchMap - start http request');
    return httpCall$.pipe(
        tap((val) => console.log('inside switchMap - http response ', val))
    );
  }
));

switchMapExample$.subscribe((val) => {
  console.table(val); // Is There a way to log only the latest value ?
}); 

Если щелкнуть внутри документа, он обработает новый запрос.

См. Блиц здесь: rxjs-about-switchmap

Использование SwitchMap позволяет отменить предыдущий запрос. Как я могу подписаться только на последний ответ на запрос?

Ответы [ 3 ]

0 голосов
/ 06 ноября 2019

Похоже на работу для exhaustMap оператора

Это как-то противоположно switchMap:

Если используется switchMap, ожидающие запросы к серверупрерваны в пользу более недавно отправленных действий. Тем не менее, если используется выхлопная карта, отправленные действия игнорируются, в то время как есть ожидающий бэкэнд-запрос.

Есть также операторы concatMap и mergeMap, которые могут работать для вас. Чтобы понять разницу между ними, взгляните на эту удивительную статью:

0 голосов
/ 07 ноября 2019

Когда последний запрос?

В какой момент времени вы определяете, какой будет последний запрос?
Вам нужно будет collect каждый клик, который делает пользователь, и в какой-то другой момент выполнить запрос. но это кажется довольно странным

Каждый наблюдаемый http-запрос будет завершен после завершения самого запроса. Если у вас нет перекрывающихся запросов, switchMap ничего не сделает, потому что нечего переключать.
Вы можете проверить это, если добавите задержку

см. https://stackblitz.com/edit/rxjs-about-switchmap-jhy3v4
Если вы добавите задержку к вашему запросу для имитации задержки, вы получите результат, который вы ожидаете получить от switchMap

Без задержки ваш запрос будет настолько быстрым, что он будет выполнен, как только вы нажмете снова, и ничего не будетпереключаться, потому что внутренняя наблюдаемая уже завершена, поэтому вы получаете все результаты, потому что это новый поток событий.
Вот почему, например, last или takeLatest здесь не помогут.

Вот что я хотел бы
https://stackblitz.com/edit/rxjs-about-switchmap-jhy3v4

В кнопке с проверкой идентификатора я бы использовал debounceTime в сочетании с switchMap и включением / выключением кнопки

const click3$ = fromEvent(document.querySelector('#test'), 'click');

switchMapExample2$.subscribe((val) => {
  console.table(val);
});

const button = document.querySelector('#test');

const switchMapExample3$ = click3$.pipe(
  tap(() => button.setAttribute('disabled', 'disabled')),
  debounceTime(500),
  tap(() => console.log('inside switchMap - click happend')),
  switchMap(() => {
    console.log('inside switchMap - start http request');
    return httpCall$.pipe(
        tap((val) => console.log('inside switchMap - http response ', val))
    );
  }));

switchMapExample3$.subscribe((val) => {
  console.table(val);
  button.removeAttribute('disabled');
});

Просто помните о RxJS: Избегайте ошибок, связанных с switchMap , опубликованных Олесом Савлуком.

0 голосов
/ 06 ноября 2019

Вы можете использовать оператор shareReplay() RxJS. Проверьте решение https://stackblitz.com/edit/rxjs-about-switchmap-9blsbq.

import { fromEvent } from "rxjs";
import { switchMap, tap, shareReplay } from "rxjs/operators";
import { ajax } from "rxjs/ajax";

const httpCall$ = ajax
  .getJSON("https://rickandmortyapi.com/api/character/")
  .pipe(
    tap(() => console.log("http request")),
    shareReplay(1),
    tap(() => console.log("http response"))
  );

const click$ = fromEvent(document, "click").pipe(
  tap(() => console.log("click happend"))
);

const switchMapExample$ = click$.pipe(switchMap(() => httpCall$));

switchMapExample$.subscribe(val => {
  console.log(val);
});
...