要求:
每次发出特定的HTTP 请求时,我都需要在 UI 上显示加载微调器。
为了获得良好的视觉效果,我决定在屏幕上显示旋转器至少1 秒,即使请求持续时间较短(事实上,它持续 0.1 秒到 3-4 分钟之间,所以最好按住旋转器至少 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
谢谢!
来自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
| 归档时间: |
|
| 查看次数: |
3021 次 |
| 最近记录: |