Search code examples
javascripthttpangularangular2-services

Angular 2 custom Http service ( on every request )


What I want to achieve is to handle somehow every Http request I'm making and on every request change my variable state. So I made my custom Http service that wraps Angular 2 Http service:

import {Injectable} from '@angular/core';
import {Http, Headers, Response} from '@angular/http';
import {Observable} from "rxjs";
import 'rxjs/add/operator/map';

@Injectable()
export class HttpClientService {
  public isLoading: boolean = false;

  constructor(private http: Http) {}

  get(url) {
    let headers = new Headers();
    this.isLoadingHttp(true);
    return this.http.get(url, {
      headers: headers
    });
  }  

  isLoadingHttp( state: boolean ): void {
    this.isLoading = state;
  }
}

So I have isLoading variable and isLoadingHttp function.

First question - Basically, on GET method started I'm setting variable to true, but how do I know when request has made and response is ready?

Second question: Do I need to make isLoading and Observable? I want to access it from my AppComponent and manipulate when to display loader whenever it has changed.


Solution

  • @Injectable()
    export class HttpClientService {
      private _isLoading: number = 0;
    
      public get isLoading () {
        return this._isLoading;
      }
    
      constructor(private http: Http) {}
    
      get(url) {
        let headers = new Headers();
        this._isLoading++;
        return this.http.get(url, {
          headers: headers
        })
        .finally(_ => this._isLoading--);
      }  
    }
    

    There can be more than one active request at a time.

    The finally operator needs to be imported like any other operator.

    @Injectable()
    export class HttpClientService {
      private requestCounter: number = 0;
      private isLoading: Subject<number> = new BehaviorSubject<number>(requestCounter);
      public readonly isLoading$:Observable<number> = this._isLoading.asObservable().share();
    
      constructor(private http: Http) {}
    
      get(url) {
        let headers = new Headers();
        this.isLoading.next(++this.requestCounter);
        return this.http.get(url, {
          headers: headers
        })
        .finally(_ => this.isLoading.next(--this.requestCounter));
      }  
    }
    

    of if you don't care how many outstanding request there are, but just if there are any

    @Injectable()
    export class HttpClientService {
      private requestCounter: number = 0;
      private isLoading: Subject<boolean> = new BehaviorSubject<boolean>(false);
      public readonly isLoading$:Observable<boolean> = this._isLoading.asObservable().share();
    
      constructor(private http: Http) {}
    
      get(url) {
        let headers = new Headers();
    
        this.requestCounter++;
        if(this.requestCounter == 1) {
          this.isLoading.next(true);
        }
        return this.http.get(url, {
          headers: headers
        })
        .finally(_ => {
          this.requestCounter--;
          if(this.requestCounter == 0) {
            this.isLoading.next(false));
          }
        })
      }  
    }