【问题标题】:How to use exhaustMap correctly Angular 7如何正确使用排气映射Angular 7
【发布时间】:2020-07-21 07:47:24
【问题描述】:

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

请在下面找到我的代码。

service.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"
            ...
>

【问题讨论】:

  • 如果你能提供更多关于服务如何工作的信息会更好。此外,如果内部 observable 仍在进行中,exhauseMap 直接忽略源 observable 通知。所以你不会从较慢的请求中得到结果。你真正需要的是concatMap
  • @Michael D 谢谢。我有两个按钮。两者都调用 initialiseGrid(),而this.state 每次都会更改以显示不同的数据。如果用户按下第一个按钮,然后按下第二个按钮,如果第一个响应比第二个慢,则网格显示第一个响应,而我需要第二个响应(因为第二个按钮最后被按下)。嗯...你是对的。我真正需要的是按照请求发生的顺序获得响应。那么,concatMap 是正确的选择吗?但是我应该如何更改我的代码以实现所需的功能?
  • 我不熟悉kendo-grid,也看不懂this.gridViewAPs = this.APsService;这行。那么kendo-grid 接受整个服务实例作为输入?
  • 是的,没错。除了实际响应(订阅结果),它也接受(使用async - telerik.com/kendo-angular-ui/components/grid/data-binding/…)。
  • 您可以使用async 管道的服务实例吗?该服务是否实现了 Observable 接口?

标签: angular rxjs angular7


【解决方案1】:

考虑一个场景,您正在使用按钮单击调用后端。您打算在用户单击“保存”按钮时将 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 请求)已经在进行中。 因此这些点击将被忽略。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 2015-12-08
    • 2022-06-22
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多