使用switchMap退订先前的http请求,仅接收最新的一个

时间:2019-04-26 12:45:36

标签: javascript angular http rxjs switchmap

我目前面临一个问题,第一次搜索可能需要5秒,而第二次搜索需要2秒,问题是,第一次搜索花费的时间更长,将“擦除”已完成请求的结果之后,因为通话在之后结束。

我试图阅读

  

switchMap

在rxJs中尝试使用它,但是根据我的尝试,它不会取消订阅先前的请求并删除结果。

这里可能是我做错了,但我无法确切指出问题所在。

合并具有3个更改结果的源(分页,排序或新的搜索条件),对sendSearchCriteria的调用将返回使用的数据。

sendSearchCriteria返回Observable

您在想什么,我做错了吗?

谢谢您的帮助,

private loadDogsResults = (filtersInformation: FilterSearchCriteria) => {
    merge(this.sort.sortChange, this.paginator.page, of(filtersInformation))
      .pipe(
        distinctUntilChanged(),
        tap(() => (this.isLoading = true)),
        switchMap(() => this.sendSearchCriteria(filtersInformation)),
        //mergeMap(() => this.sendSearchCriteria(filtersInformation)),
        map(data => this.formatResults(data)),
        finalize(() => (this.isLoading = false)),
        catchError(error => this.handleError(error)),
        takeUntil(this._onDestroy$)
      )
      .subscribe((result: any[]) => {
        if (result.length > 0) {
          this.setDisplayedColumns(result[0]);
        }
        this.isLoading = false;
      });
  }

3 个答案:

答案 0 :(得分:2)

哪个事件触发search?此事件应该是您的Observable的来源,它将与switchMap运算符一起“输送”。

正如我在这里看到的那样,如果您为每个事件调用loadDogsResults(),则每次创建一个新的Observable时将不起作用。 of(filtersInformation)是一个Observable,它在订阅了Observable时会一次发出filtersInformation值,我认为这不是预期的行为。

答案 1 :(得分:1)

您正在对3个单独的可观察对象进行合并,这将导致您在3个不同的场合进入管道,并触发3个对sendSearchCriteria的单独调用。如果要执行的操作是调用sortChange和page,获取两者的结果,然后调用sendSearchCriteria,则可以...

private loadDogsResults = (filtersInformation: FilterSearchCriteria) => {
    forkJoin(this.sort.sortChange, this.paginator.page)
      .pipe(
        distinctUntilChanged(),
        tap(() => (this.isLoading = true)),
        switchMap(() => this.sendSearchCriteria(filtersInformation)),
        //mergeMap(() => this.sendSearchCriteria(filtersInformation)),
        map(data => this.formatResults(data)),
        finalize(() => (this.isLoading = false)),
        catchError(error => this.handleError(error)),
        takeUntil(this._onDestroy$)
      )
      .subscribe((result: any[]) => {
        if (result.length > 0) {
          this.setDisplayedColumns(result[0]);
        }
        this.isLoading = false;
      });
  }

但是请记住,在订阅中,您只能访问sendSearchCriteria的响应。

答案 2 :(得分:0)

一个同事帮助我找到了问题:)我们尝试了forkJoin,combinateLatest和多个选项,但最大的问题是以奇怪的方式完成了初始化/订阅。

我们现在创建了searchTriggerSubject并添加了这些行

  private initializeSubscription() {
    this.searchTriggerSubscription = this.searchTriggerSubject.pipe(
      tap(() => (this.isLoading = true)),
      switchMap(() => this.sendSearchCriteria(this.claimsFilters)),
      map(data => this.formatResults(data)),
      catchError(error => this.handleError(error)),
      takeUntil(this._onDestroy$)
    ).subscribe((result: any[]) => {
    if (result.length > 0) {
      this.setDisplayedColumns(result[0]);
    }
    this.isLoading = false;
  });
  }

  private initializeSearchTriggerValues() {
    this.sort.sortChange.subscribe(() => this.searchTriggerSubject.next())
    this.paginator.page.subscribe(() => this.searchTriggerSubject.next())
    this.filtersSubscription = this.claimsFiltersService.getFilterValues()
    .pipe(
      filter(filters => filters !== null),
      tap((filter) => this.claimsFilters = filter)
    )
    .subscribe(() => this.searchTriggerSubject.next());
  }

过滤器是从服务中提供的,因此,我们为避免该问题做了此事。

需要一些重构

非常感谢每个人的不同潜在客户,拥有多个主题可以使工作更加轻松