Angular RxJS:事件发出两次

时间:2019-05-28 11:30:24

标签: angular typescript rxjs

我已经编码了两个可观察对象:

一个用于提交表单提交事件的事件:

<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时,我都会使用自定义的可传递函数发出requestm:

    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管道创建订阅:

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

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

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

您两次订阅了可观察的metrics$。这是发生了什么:

  1. 您使用*ngIf="!(metrics$ | async)"进行订阅。
  2. 当您单击搜索时,它会立即触发可观察对象,以及您链接到该对象上的所有内容,包括您的请求。
  3. 您使用*ngIf="metrics$ | async; let metric;"进行订阅。
  4. 第2步分别再次发生。

使用share()中的metrics$运算符可以防止在新订阅上重新发出请求。如果您想更深入地了解此主题,请查看此great article

答案 1 :(得分:1)

您已经订阅了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>

有关更多详细信息,请参见Handling observables with NgIf & Async Pipe