используя switchMap, чтобы отписаться от предыдущего http-запроса и принять только последний - PullRequest
2 голосов
/ 26 апреля 2019

В настоящий момент я сталкиваюсь с проблемой, когда первый поиск может занять 5 секунд, а второй, который занимает 2 секунды, проблема в том, что первый поиск, который занимает больше времени, «сотрет» результаты выполненного запроса.после, потому что вызовы заканчиваются после.

Я пытался прочитать о

switchMap

в rxJs и пытался использовать его, но из того, что я пытаюсь, он не отменяет подписку на предыдущий запрос и стирает результат.

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

Слияние имеет 3 источника изменения результата (разбивка на страницы, сортировка или новые критерии поиска), и вызов sendSearchCriteria возвращает используемые данные.

sendSearchCriteria возвращает Observable * 1018.*

есть что-нибудь, что вам приходит в голову, что я делаю не так?

Спасибо за вашу помощь,

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 ]

2 голосов
/ 26 апреля 2019

Какое событие вызывает search?Это событие должно быть источником вашего Observable, который будет "передан" с оператором switchMap.

Как я вижу здесь, если вы вызываете loadDogsResults() для каждого события, оно не будетработать, как вы создаете новый Observable каждый раз.of(filtersInformation) - это Наблюдаемое, которое выдает значение filtersInformation ОДИН РАЗ, когда подписка на Наблюдаемое, я не думаю, что это ожидаемое поведение.

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

Вы выполняете слияние с 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.

0 голосов
/ 29 апреля 2019

Коллега помог мне найти проблему :) мы попробовали forkJoin, объединить последние и несколько вариантов, но самой большой проблемой была инициализация / подписка, выполненная нечетным образом.

теперь мы создали 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());
  }

фильтры приходили из службы, поэтому мы сделали это, чтобы избежать этой проблемы.

Необходим некоторый рефакторинг

Большое спасибо всем за разные ссылки,наличие нескольких предметов облегчает

...