1

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.

1
  • Yes, you may want to add isLoading$ observable (most likely a subject) as well, because it makes sense here. It probably should be a separate service. Commented Feb 11, 2017 at 12:04

1 Answer 1

4
@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));
      }
    })
  }  
}
Sign up to request clarification or add additional context in comments.

6 Comments

how can I observe _isLoading ?In my AppComponent I initialize it like this isLoading: number = this._http.isLoading; but it doesn't seem to work
You can use for example <div *ngIf="_http.isLoading"> to let Angular change detection update the view depending on isLoading or alternatively (usually a better approach) to use a BehaviorSubject and subscribe to it. I'll update my answer to demonstrate it.
I'm getting this error (Property 'emit' does not exist on type 'Subject<boolean>) on this line : this.isLoading.emit(true);
Sorry, I mixed up emit with next. emit is from EventEmitter. I updated my answer.
It's similar to what is used in angular.io/docs/ts/latest/cookbook/…. See also stackoverflow.com/questions/35142968/… (especially "That means that no one has access to the upstream Observable.") - it's just some basic encapsulation to hide implementation details from users of your API.
|

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.