The requirement:
I need to show a loading spinner on UI each time when a specific HTTP request is made.
In order to have a nice visual aspect, I decided to show the spinner on screen for at least 1 second, even if the request lasts less (in fact, it lasts between 0.1s and 3-4 minutes, so better to hold the spinner for at least 1 second). So, the conditions are:
- if the request takes less than 1s, the spinner will show for 1 second
- if the request takes longer than 1s, the spinner will show till it finishes.
I know that this approach can be debatable from UI/UX perspective - but I prefer to consider it as a technical challenge.
The code I've tried:
As found on other implementation on SO, I've tried an approach with combineLatest - combine an Observable that takes 1s and the Observable for the http request.
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);
});
}
This works well if the HTTP request returns with status 200.
The problem:
The code above does not work if the HTTP request returns an error (4/5xx). The Observables finish right after the HTTP request ends.
I want the spinner to have the same behavior even if the request finishes first, with an error.
I've made a simple Stackblitz, where we can play with different requests: https://stackblitz.com/edit/spinner-with-min-duration-zcp7hc
Thanks!