【问题标题】:Show loading indicator in Angular while waiting for a RxJS observable在等待 RxJS 可观察对象时在 Angular 中显示加载指示器
【发布时间】:2019-05-15 00:21:03
【问题描述】:

我有一个 Angular 组件,它侦听路由参数以更改用户 ID,并在它发生更改时加载用户详细信息。用户详细信息需要几秒钟才能从 API 返回数据。

如果我正在查看用户 A 的详细信息,然后单击以查看用户 B 的详细信息,它将继续显示用户 A,直到在我单击几秒钟后返回用户 B 的详细信息。有没有办法在为用户 B 检索数据时显示加载指示器或将其空白?

用户详情组件:

ngOnInit(): void {
  this.userDetails = this.route.paramMap.pipe(
    switchMap((params: ParamMap) => this.userService.getUserDetails(+params.get('userId')))
  );
}

用户详情模板:

<div *ngIf="userDetails | async as userDetails">
  <h1>{{userDetails.firstName}} {{userDetails.lastName}}</h1>
</div>

如果内部 switchMap 当前正在运行,我希望用户详细信息 div 为空白或显示某种加载指示器。我知道一个选择是有一个加载变量,我在 switchMap 之前设置为 true,在 switchMap 之后设置为 false,并在 div 的 *ngIf 中使用它,但我希望有一种更流畅的方式不必有为每一种情况加载变量。

我有一个 StackBlitz 示例: https://stackblitz.com/edit/angular-ng-busy-yxo1gu

目标是当我单击用户 B 按钮时,用户 A 信息应该在用户 B 加载时消失。我的应用中有几十个这样的场景,所以我正在寻找最干净的方法来做到这一点。

【问题讨论】:

    标签: angular rxjs observable


    【解决方案1】:

    你可以改变你的 *ngIf

    ngIf="userDetails | async as userDetails else #loading"
    

    然后

    <div #loading>
      loading...
    </div>
    

    Reference

    【讨论】:

    • 这适用于加载第一个用户。但是当我点击另一个用户时,它会继续显示第一个用户的信息,直到新用户完成加载,因为该组件被重用。
    • 如果你在开始异步操作之前分配this.userDetails = null,那一刻它是未定义的,所以它落入else块
    • 我在我的模板中收到此错误:解析器错误:第 76 列的意外标记#
    • @FlorianLeitgeb 这可能对初学者有所帮助,所以我决定添加此评论,Angular ngIf 指令 else 块只需要模板名称,因此您不能将 # 与模板名称放在此处。它应该是ngIf="userDetails | async as userDetails else loading" ,另外我认为你应该使用&lt;ng-template #loading&gt;...&lt;/ng-template&gt; 在html中设置你的加载块。
    【解决方案2】:

    如果您只想让内容消失,您可以在开始获取其他用户时发出例如null

    this.userDetails = this.userId.asObservable().pipe(
      switchMap(id => merge(
        of(null),
        this.getUserDetails(id)
      )),
    );
    

    merge Observable 创建方法将重新发出 emit null 然后等到 getUserDetails 完成。你甚至不需要ng-busy

    您更新的演示:https://stackblitz.com/edit/angular-ng-busy-vwteyf?file=src/app/app.component.ts

    【讨论】:

      【解决方案3】:

      您可以使用ng-busy(或基本上任何其他 npm 组件)在您的应用中的每个 http 调用(在您的情况下为承诺或可观察的)显示加载指示器。

      编辑:关于您使用 Observable 的事实,您可以使用 .toPromise 来使用 ng-Busy。修改了 DEMO 以向您展示如何做到这一点。

      这是 ng-busy 的 Minimal, Complete, and Verifiable example,正在处理您的代码。

      【讨论】:

      • 这非常接近,但我的 userDetails 是可观察的。我拿走了你的 stackblitz 并将其修改为更接近我使用 userDetails 所拥有的内容。在我的应用程序中我有几十个这样的场景,所以我正在寻找在用户单击用户 B 按钮后删除用户 A 详细信息的最巧妙方法。 stackblitz.com/edit/angular-ng-busy-yxo1gu
      • @Jeremy 你看到更新的演示了吗?对你有帮助吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 2016-01-17
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多