有没有办法只订阅SwitchMap的最新响应?

时间:2019-11-06 11:03:13

标签: angular rxjs observable switchmap

考虑以下示例:


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 :(得分:1)

您可以使用RxJS的shareReplay()运算符。查看解决方案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);
});

答案 1 :(得分:0)

似乎是exhaustMap operator的工作

switchMap相反:

  

如果使用switchMap,则挂起的后端请求将被中止,转而使用最近分发的操作。但是,如果使用了exhaustMap,则在有待处理的后端请求时,将忽略调度的操作。

还有concatMapmergeMap个运算符可能对您有用。为了了解它们之间的区别,请看这篇很棒的文章:

答案 2 :(得分:0)

最近的请求是什么时候?

您将在什么时间定义最新请求?
您需要collect用户每次单击,然后在其他时候执行请求。但这看起来很奇怪

请求本身完成后,每个可观察到的http请求都会完成。 如果您没有任何重叠的请求,switchMap不会做任何事情,因为没有任何可切换的内容。
您可以验证是否添加了延迟

请参见https://stackblitz.com/edit/rxjs-about-switchmap-jhy3v4
如果您在请求中添加延迟以模拟延迟,那么您将从switchMap

获得预期的结果

在没有延迟的情况下,您的请求是如此之快,以至于您再次单击就可以完成,并且因为内在的可观测对象已经完成而没有任何切换,因此您得到了所有结果,因为它是新的事件流。 > 这也是为什么lasttakeLatest在这里无济于事的原因。

这就是我要
https://stackblitz.com/edit/rxjs-about-switchmap-jhy3v4

在ID测试按钮中,我将debounceTimeswitchMap结合使用并启用/禁用按钮

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');
});

请注意Oles Savluk发布的RxJS: Avoiding switchMap-Related Bugs