首页 > 解决方案 > 如何正确使用排气映射Angular 7

问题描述

网格使用 绑定到服务async。在多个情况下使用相同的服务(模式 -state然后进行更改)我发现有时第二个请求首先完成,然后第一个请求完成。然后网格显示来自第一个响应的数据,而我需要它来显示来自最后一个响应的数据。所以,我想使用exhaustMap来等待响应完成,然后再触发一个新请求。

请在下面找到我的代码。

服务.ts

public query(token: string, tableName: string, state: any): void {
    console.log("state in query", state);
    this.fetch(token, tableName, state)
        .subscribe((x: any) => {
            console.log("response data", this.data);
            super.next(x);
            this.isLoading = false;
            this.mediatorService.sendMessage("APsRefreshed");
        },
            (err: any) => {
                console.log("err", err);
                this.isLoading = false;
            }
        );
}

public fetch(token: string, tableName: string, state: any): Observable<any> {
    let queryStr = `${toODataString(state)}&$count=true`;
    queryStr = queryStr.replace(/('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')/ig, function (x) {
        return x.substring(1, x.length - 1);
    });
    queryStr = queryStr.replace(/substringof\((.+),(.*?)\)/, "contains($2,$1)");
    const regex = /T00:00:00\.000Z/gi;
    const noTimeZoneQueryStr = queryStr.replace(regex, '');
    let fetchCallResult = this.http
        .get(`${this.BASE_URL}` + `/` + token + `${tableName}&${noTimeZoneQueryStr}`)
        .pipe(
            map((response: any) => ((<any>this.data) = {
                data: response['value'],
                total: parseInt(response['@odata.count'], 10)
            }
            ))
    );
    return fetchCallResult;
}

组件.ts

public initialiseGrid() {
    this.APsService.isLoading = true;
    this.gridViewAPs = this.APsService;
    this.APsService.query(this.token, this.tableName, this.state);
}

模板.html

<kendo-grid #gridView
            [data]="gridViewAPs | async"
            [loading]="APsService.isLoading"
            ...
>

标签: angularrxjsangular7

解决方案


考虑一个场景,您正在使用按钮单击来调用后端。您打算在用户单击“保存”按钮时将 PUT 请求发送到后端。

因此,您的代码最初看起来像这样。

  fromEvent(this.saveButton.nativeElement, 'click')
  .pipe(
      concatMap(changes => this.saveCourse(changes))
  ).subscribe();

在这里,如果你继续使用 concatMap 并快速点击 N 次“保存”按钮,将向后端发出 N 次请求。

但是,如果您使用这样的排气映射:

  fromEvent(this.saveButton.nativeElement, 'click')
  .pipe(
      exhaustMap(changes => this.saveCourse(changes))
  ).subscribe();

那么您的请求将被发送更少的次数。

使用 'exhaustMap' 的原因是,只要内部 observable 仍在进行中,来自源 observable 的值就会被忽略。

因此,在这种情况下,在您的某些点击期间(被视为源 observable),内部 observable(即 put 请求)已经在进行中。因此,这些点击将被忽略。


推荐阅读