【问题标题】:angular async reloading spinner角度异步重新加载微调器
【发布时间】:2019-07-11 06:56:33
【问题描述】:

当异步管道为空时,我有一个简单的设置来显示加载微调器:

<div *ngIf="(searchResults$ | async) as searchResults; else loading">
</div>
<ng-template #loading>
    loading..
</ng-template>

但是,当用户再次搜索时,加载.. 不显示,我想我需要这个 searchResults$ observable 发出 null 以再次显示微调器,或者有一个单独的 isLoading 变量。

最好的方法是什么?

如果重要的话,我有一个 debounce 和一个 switchMap(即使用 finalize 等很棘手)

this.searchResults$ = this.filters$
      .pipe(
        debounceTime(200),
        distinctUntilChanged(),
        switchMap((f) => {
            return httpGet(f)
        })
      )

另外,我尝试了*ngIf="!isLoading &amp;&amp; (searchResults$ | async) as searchResults,但发现它有问题,例如searchResults$ 未订阅,或在更改检测后抱怨更改

【问题讨论】:

  • 您能否使用 isLoading 解决方案提供您的代码?你提到的问题应该是可以解决的,我认为它比让 searchResults observable 发出空值来指示加载更清晰
  • @rh16 在 switchmap 中,设置 this.isLoading = true,然后 httpGet(f).pipe( set isLoading=false )。尝试在异步管道之前和之后将 isLoading 放入模板中。
  • 问题可能是返回 httpGet(f).pipe(),取决于管道内的内容,可能会丢弃 httpGet(f) 的返回。就像我说的那样,我不喜欢让 searchResults$ 发出空值,因为我认为它会破坏代码的清晰度,但如果你对这个解决方案感到满意,我会把它留在那里
  • @rh16 谢谢 - 是的,我同意发出空值并不理想。我希望在未来的某一天看到一个更好的解决方案,因为我最终每个项目都需要多次这样做。

标签: angular rxjs observable switchmap


【解决方案1】:

您可以尝试使用点击运算符设置 isLoading 变量,如下所示:

this.searchResults$ = this.filters$
      .pipe(
        debounceTime(200),
        distinctUntilChanged(),
        tap(() => {this.isLoading = true}),
        switchMap((f) => {
            return httpGet(f)
        }),
        tap(() => {this.isLoading = false})
      );

然后,您可以通过将其托管在 ng-container 元素内的不同 *ngIf 中来绕过不订阅您的 observable 的角度。

<ng-container *ngIf="(searchResults$ | async) as searchResults">
  <div *ngIf="!isLoading"></div>
</ng-container>
<ng-template *ngIf="isLoading">
    loading..
</ng-template>

【讨论】:

  • 还有一件事是错误捕获并将 isLoading 设置为错误时为 false。其他解决方案也没有考虑到一些事情。见codinglatte.com/posts/angular/angular-async-pipe-handle-errors
  • @robertking 您可以添加一个 catchError 调用到将 isLoading 设置为 false 的管道,您可能还希望在此处设置一个 isError 变量(并在第一次点击调用中取消设置),以便您可以显示一些某种错误信息
【解决方案2】:

我遇到了同样的问题并解决了区分“询问”流和“结果”流的问题,将两者合并为可观察的组件结果。 像这样的东西(基于你的代码):

this.searchResults$ = merge(
      this.filters$.pipe(map(f => null)),
      this.filters$.pipe(
        debounceTime(200),
        distinctUntilChanged(),
        switchMap((f) => {
            return httpGet(f)
        })
      )
    );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 2017-01-26
    • 2019-01-06
    • 2021-04-23
    • 1970-01-01
    相关资源
    最近更新 更多