Angular 2+ HTTP 请求 - 显示成功和错误响应的最短持续时间的加载微调器

and*_*tor 5 rxjs angular

要求

每次发出特定的HTTP 请求时,我都需要在 UI 上显示加载微调器。

为了获得良好的视觉效果,我决定在屏幕上显示旋转器至少1 秒,即使请求持续时间较短(事实上,它持续 0.1 秒到 3-4 分钟之间,所以最好按住旋转器至少 1 秒)。所以,条件是:

  • 如果请求时间少于1 秒,微调器将显示 1 秒
  • 如果请求花费的时间超过1 秒,旋转器将显示直到完成。

我知道这种方法从 UI/UX 角度来看可能存在争议 - 但我更愿意将其视为技术挑战。

我尝试过的代码:

正如在 SO 的其他实现中发现的那样,我尝试了一种方法combineLatest- 将需要 1 秒的 Observable 和用于 http 请求的 Observable 结合起来。

load() {
  this.loading = true; // this will show the spinner
  combineLatest(timer(1000), this.service.apiCall())
    .pipe(
      finalize(()=> {
        this.loading = false; // this will hide the spinner
      }),
      map(x => x[1])
    )
    .subscribe(x => {
      console.log(x);
    });
}
Run Code Online (Sandbox Code Playgroud)

如果 HTTP 请求返回状态为 200,则此方法效果很好。

问题:

如果 HTTP 请求返回错误 (4/5xx),则上述代码不起作用。HTTP 请求结束后 Observables 立即完成。

我希望微调器具有相同的行为,即使请求先完成但出现错误。

我做了一个简单的 Stackblitz,我们可以在其中处理不同的请求: https://stackblitz.com/edit/spinner-with-min-duration-zcp7hc

谢谢!

Mad*_*ted 1

来自rxjs文档:

如果至少有一个 Observable 被传递给combineLatest,并且所有传递的 Observable 发出了一些东西,则当所有组合流完成时,生成的 Observable 将完成。...另一方面,如果任何 Observable 出现错误,combineLatest 也会立即出错,并且所有其他 Observable 都将被取消订阅。

因此,您必须使用catchError管道使用其自己的错误捕获例程来处理导致可观察到的错误,这样它就不会向combineLatest操作员抛出错误。像这样的东西会起作用。

load() {
  this.loading = true; // this will show the spinner
  combineLatest(timer(1000), 
    this.service.apiCall().pipe(
        catchError(err)=>{
            return of(err); // Return observable wrapped with error.
        }))
    .pipe(
      finalize(()=> {
        this.loading = false; // this will hide the spinner
      }),
      map(x => x[1])
    )
    .subscribe(x => {
      console.log(x);
      //Check in the result if there is an error in http
      if(x instanceof HttpErrorResponse) {
           // do what you want in error scenario.
      }
    });
}
Run Code Online (Sandbox Code Playgroud)

Stackblitz 演示: https://stackblitz.com/edit/spinner-with-min-duration-ls9dq7