Angular RxJS: событие, выпущенное дважды - PullRequest
1 голос
/ 28 мая 2019

Я кодировал две наблюдаемые:

Один для отправки формы событий:

<form role="form" (ngSubmit)="search()">
   ...
</form>

А search() достигается и выдает:

private search(): void {
    this.searchClickSubject.next();
}

В конструкторе компонентов:

private searchClickSubject:Subject<void>;
private searchClick$:Observable<any>;

constructor() {
    this.searchClickSubject = new Subject<void>();
    this.searchClick$ = this.searchClickSubject.asObservable();
}

Как видите, я создаю Observable из субъекта searchClickSubject, используя метод searchClickSubject.asObservable для searchClick$.

С этого момента я использую это searchClick$ Наблюдаемое для того, чтобы поймать submit form.

После этого я создаю еще одну Observable:

    this.searchQuery$ = this.searchClick$.pipe(
        map(() => <Query>{
            offset: 0,
            limit: 10
        })
    );

Итак, каждый раз, когда выдается Query, я делаю запрос, используя пользовательские конвейерные функции:

    this.metrics$ = this.searchQuery$
        .pipe(
          pageLoading(),
          makeRequest(),
          loadedPage()
        );

Это мой ngOnInit():

public ngOnInit() {            
    // Grab search button click event
    this.searchQuery$ = this.searchClick$.pipe(
        map(() => <Query>{
            offset: 0,
            limit: 10
        })
    );

    this.metrics$ = this.searchQuery$
        .pipe(
          //...
        );
}

Однако запрос запускается дважды.

Я создаю подписки, используя async pipe:

<div class="row" *ngIf="!(metrics$ | async)" style="margin: 1.54em;">

<div *ngIf="metrics$ | async; let metric;"...

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 28 мая 2019

Вы подписываетесь на наблюдаемую metrics$ два раза. Вот что происходит:

  1. Вы подписываетесь, используя *ngIf="!(metrics$ | async)".
  2. Когда вы нажимаете кнопку поиска, она сразу же запускает наблюдаемое и все, что вы приковали к нему, включая ваш запрос.
  3. Вы подписываетесь, используя *ngIf="metrics$ | async; let metric;".
  4. Шаг 2 происходит снова, отдельно.

Используйте оператор share() в metrics$, чтобы предотвратить повторный запрос на новую подписку. Если вы хотите глубже понять эту тему, прочитайте эту замечательную статью .

1 голос
/ 28 мая 2019

Вы подписались на metrics$ два раза, вместо этого вы можете использовать синтаксис as, как показано ниже

<div *ngIf="metrics$ | async as metric; else loading">
   <!-- Statements when metrics data found  -->
</div>

<ng-template #loading>
   <!-- Loading stuff...  -->
  <div class="row" style="margin: 1.54em;">
</ng-template>

См. Обработка наблюдаемых с NgIf & Async Pipe дляболее подробная информация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...