Angular异步重新加载旋转器

5

我有一个简单的设置,当异步管道为空时显示加载小图标:

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

然而,当用户第二次搜索时,加载中的提示不会显示。我认为需要让searchResults$可观察对象再次发出null来重新显示旋转图标,或者使用一个单独的isLoading变量。有什么最好的方法吗?如果有影响的话,我使用了防抖和switchMap(即使用finalize等操作比较棘手)。
this.searchResults$ = this.filters$
      .pipe(
        debounceTime(200),
        distinctUntilChanged(),
        switchMap((f) => {
            return httpGet(f)
        })
      )

此外,我尝试过*ngIf="!isLoading && (searchResults$ | async) as searchResults,但发现存在问题,例如未订阅searchResults$,或Angular在变更检测后抱怨变更。


你能否提供使用isLoading解决方案的代码?你提到的问题应该是可以解决的,而且我认为这比让searchResults可观测对象发出空值来表示加载更清晰。 - rh16
在 switchmap 中,设置 @rh16.isLoading = true,然后 httpGet(f).pipe(set isLoading=false)。尝试将 isLoading 放置在模板中,在管道到 async 之前和之后都可以。 - Rusty Rob
问题可能在于返回httpGet(f).pipe(),取决于管道内部的内容,可能会丢弃httpGet(f)的返回值。就像我说的,我不喜欢让searchResults$发出null,因为我认为它可能会削弱代码的清晰度,但如果您对这个解决方案感到满意,我会让它保持不变。 - rh16
@rh16 谢谢 - 是的,我同意发出 null 不是理想的选择。我希望将来有一个更好的解决方案,因为这是我在每个项目中都需要多次使用的东西。 - Rusty Rob
3个回答

4
您可以尝试使用tap操作符设置isLoading变量,如下所示:

您可以尝试使用tap操作符设置isLoading变量,如下所示:

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

您可以通过将可观察对象放置在不同的 *ngIf 内,托管在 ng-container 元素中,绕过 Angular 不订阅它的问题。

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

还有一件事是错误捕获并在出现错误时将isLoading设置为false。这也是另一个解决方案没有考虑到的。请参见https://codinglatte.com/posts/angular/angular-async-pipe-handle-errors/。 - Rusty Rob
1
@robertking 你可以在管道中添加一个catchError调用,将isLoading设置为false。你可能还想在这里设置一个isError变量(并在第一个tap调用中取消设置),以便您可以显示某种错误消息。 - rh16

2
我曾经遇到过同样的问题,并通过区分“询问”流和“结果”流来解决,将两者合并为组件结果可观察对象。类似于这样(基于你的代码):

我遇到了同样的问题并解决了区分“ask”流和“result”流,将两者合并为组件结果可观察对象。类似于这样(基于您的代码):

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

0

我现在使用ngx-http-request-state库,它提供了加载、错误和渲染状态。如果使用scan()或withLatestFrom(),它还可以在重新加载时工作。此外,它还可以从内部可观察对象中工作。

如果使用graphql,我建议使用fetchPolicy、loading和networkStatus的组合选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接