2

Here is my LoadingScreenService:

    import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
import { NavigationStart, NavigationEnd, Router, NavigationCancel } from '@angular/router';

@Injectable()
export class LoadingScreenService {

  private loadingScreenEl: HTMLElement = null;
  private player: AnimationPlayer;

  private isEnabled = false;
  private isShowing = false;
  private isHiding = false;

  constructor(
    private animationBuilder: AnimationBuilder,
    @Inject(DOCUMENT) private document: any = null,
    private router: Router = null
  ) {
    if (document !== null) {
      this.loadingScreenEl = this.document.body.querySelector('#fuse-loading-screen');
    }

    if (router !== null) {
      this.router.events.subscribe((event) => {
          if (event instanceof NavigationStart) {
            setTimeout(() => {
              this.show();
            }, 0);
          }
          if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
            setTimeout(() => {
              this.hide();
            }, 0);
          }
        }
      );
    }
  }

  /**
   * @param {number} wait Duration (ms) of a timeout before showing the spinner
   */
  show(wait: number = 1000) {
    if (this.isEnabled || this.isShowing) {
      return;
    }

    this.isShowing = true;
    this.player =
      this.animationBuilder
        .build([
          style({
            opacity: '0',
            zIndex : '9999'
          }),
          animate('200ms ease', style({opacity: '1'}))
        ]).create(this.loadingScreenEl);

    this.isEnabled = true;

    setTimeout(() => {
      this.player.play();

      setTimeout(() => {
        this.isShowing = false;
      }, 200);
    }, wait);

  }

  hide() {
    if (!this.isShowing
      && (!this.isEnabled || this.isHiding)) {
      return;
    }

    this.isHiding = true;
    this.player =
      this.animationBuilder
        .build([
          style({opacity: '1'}),
          animate('200ms ease', style({
            opacity: '0',
            zIndex : '-20'
          }))
        ]).create(this.loadingScreenEl);

    setTimeout(() => {
      this.isEnabled = false;
      this.player.play();

      setTimeout(() => {
        this.isHiding = false;
      }, 200);
    }, 0);
  }
}

And I'm trying to use show/hide methods whenever I'm making a request to backend.

Here is what I got so far but I cannot find a way to properly put my subscriveLoading() method into intercept().

   import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { LoadingScreenService } from '../../core/services/loading-screen.service';

@Injectable()
export class LoadingInterceptor implements HttpInterceptor {

  constructor(
    private loadingScreenService: LoadingScreenService
  ) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

  }

  private subscribeLoading(): Observable<any[]> {
    this.loadingScreenService.show();

    const observable;
    observable.subscribe(() => {
      this.loadingScreenService.hide();
    }, err => {
      this.loadingScreenService.hide();
      return err;
    }); // Pass the error to other observers

    return observable;
  }
}

Is there some easy way to use my LoadingScreenService to intercept every call and use show method form mentioned service while I'm waiting for response from backend?

1 Answer 1

4

Here is a way to use your service in an interceptor

On intercept you start to show your loader, then your intecept return the request with a finally operator that will hide the on success or error

@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
    constructor(
        private loadingScreenService: LoadingScreenService
    ) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.loadingScreenService.show();

        return next.handle(req).pipe(finalize(() => {
            this.loadingScreenService.hide();
        }));
    }
}

BUT : if you have two concurrent requests, when the first request will end, it will hide the loader even if the second request is not finished.

You should have a counter of pending request in your service :

@Injectable()
export class LoadingScreenService {
....
    private counter: number: 0;
...

show(wait: number = 1000) {
        this.counter++;
....
}

hide() {
        this.counter--;
        if (this.counter > 0) return;
...
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.