I want to show a loader when async loading an Angular route config, however sometimes these can load very fast and the loader just flashes on screen for a split second.
I want to instead only show the loader if it has not finished loading after a period of time. My first thought was to use delay(250)
. This works when navigating to that page with the needed config, but if I refresh that page it seems to always flash the loader on screen for a brief moment
Here's what I am doing right now
private isLoadingRouteConfig = false;
readonly isLoadingRouteConfig$ = this.router.events.pipe(
delay(250), //if the config loads very quickly, don't even show this
map((ev) => {
if (ev instanceof RouteConfigLoadStart) {
this.isLoadingRouteConfig = true;
} else if (ev instanceof RouteConfigLoadEnd) {
this.isLoadingRouteConfig = false;
}
return this.isLoadingRouteConfig;
}),
);
@if (isLoadingRouteConfig$ | async) {
<app-loader />
}
How can I make this work as I would expect it to? I want to show a loader after 250ms, but skip this if it has completed loading already.
Your delay operator will also delay the RouteConfigLoadEnd event, which I assume you do not want. Try using timer instead of delay, and switchMap to cancel the timer if RouteConfigLoadEnd is received:
readonly isLoadingRouteConfig$ = this.router.events.pipe(
filter(ev => ev instanceof RouteConfigLoadStart || ev instanceof RouteConfigLoadEnd),
switchMap(ev => (ev instanceof RouteConfigLoadStart ? timer(250).pipe(map(() => true)) : of(false))));