angularrxjs

How to display an Angular route config loader after a specified delay?


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.


Solution

  • 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))));