AHmedRef
AHmedRef

Reputation: 2611

Detect the begin of any http request and the finish of all requests in angular2

is there any possibility to detect the begin of any http request and when calls are finished in angular2 ? this is my custom http service :

import {Injectable, Inject} from "@angular/core";
import { Http, Response, Headers, RequestOptions } from "@angular/http";
import { StorageServiceClass } from "../storage.service";
import "rxjs/add/operator/map";
import * as Cookies from "js-cookie";

import { Observable }   from "rxjs/Rx";
import {  Router } from "@angular/router";


@Injectable()
export class HttpClient {

    public storage: StorageServiceClass;

    private http: Http;
    private router: Router;

    constructor(private _http: Http, _router: Router, private _storage: StorageServiceClass) {
        this.http = _http;
        this.router = _router;
        this.storage = _storage;
    }

    public setToken() {
        let token = Cookies.get("authToken");
        if (token !== "undefined" && token !== undefined) {
            this.storage.setAuthToken(token);
        }
    }

    public removeStorageAndCookies() {
        Cookies.remove("authToken");
        this.storage.removeAuthToken();
    }

    public createAuthorizationHeader(headers: Headers) {
        let token = this.storage.getAuthToken();
        headers.append("Accept", "application/json");
        headers.append("Content-Type", "application/json");

        if (token !== null && token !== undefined) {
            headers.append("Authorization", "JWT " + token);
        }
    }

    public post(url: string, data: any, options?: RequestOptions) {
        let headers = new Headers();
        if (options !== undefined) {
            headers = options.headers;
        }
        this.createAuthorizationHeader(headers);
        let dataResp = this.intercept(this.http.post(url, data, { headers: headers, withCredentials: true }));
        this.setToken();
        return dataResp;
    }


    public put(url: string, data: any, options?: RequestOptions) {
        let headers = new Headers();
        if (options !== undefined) {
            headers = options.headers;
        }
        this.createAuthorizationHeader(headers);
        let dataResp = this.intercept(this.http.put(url, data, { headers: headers, withCredentials: true }));
        this.setToken();
        return dataResp;
    }

    public delete(url: string, options?: RequestOptions) {
        let headers = new Headers();
        if (options !== undefined) {
            headers = options.headers;
        }
        this.createAuthorizationHeader(headers);
        let dataResp = this.intercept(this.http.delete(url, { headers: headers, withCredentials: true }));
        this.setToken();
        return dataResp;
    }


    public get(url: string, data?: any, options?: RequestOptions) {
        let headers = new Headers();
        if (options !== undefined) {
            headers = options.headers;
        }
        this.createAuthorizationHeader(headers);

        let urlParams = "";
        if (data) {
            urlParams = jQuery.param(data);
        }

        let dataResp = this.intercept(this.http.get(url, {
            headers: headers, search: urlParams, withCredentials: true
        }));
        this.setToken();
        return dataResp;
    }

    public intercept(observable: Observable<Response>): Observable<Response> {
        return observable.catch((err, source) => {
            if (err.status === 401) {
                this.removeStorageAndCookies();
                this.router.navigate(["login"]);
                return Observable.empty();
            } else {
                return Observable.throw(err);
            }
        });
    }

}

Upvotes: 1

Views: 2277

Answers (1)

KwintenP
KwintenP

Reputation: 4775

The recommended way of doing this in angular 2 is providing a httpwrapper service. This could look like this:

@Injectable()
export class CustomHttp extends Http {
    private activeCalls: number;
    private store: Store<ApplicationState>;

    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, store: Store<ApplicationState>) {
        super(backend, defaultOptions);
        this.store = store;
        this.activeCalls = 0;
    }

    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
        this.httpCallRequested();

        return super.get(url, options).finally(
            () => {
                this.httpCallReady();
            }
        );
    }
}

This is an incomplete example. Find the full one here: https://github.com/brechtbilliet/winecellar/blob/master/src/app/customHttp.ts

This class wraps all the http calls and allow you to do something before and after execution. To use this wrapper everywhere instead of the normal HTTP service you should provide this class at your app module. This can be done like this:

@NgModule({
    imports: [BrowserModule, AboutModule, AuthenticationModule, CommonLogicModule, StockModule, routing],
    declarations: [ApplicationContainer],
    exports: [ApplicationContainer],
    providers: [
        AppSandbox,
        {
            provide: Http,
            useFactory: customHttpFactory,
            deps: [XHRBackend, RequestOptions, Store]
        }
    ]
})

Notice the providers part. Every module underneath this module will get an instance of the httpWrapper if they inject 'Http' thanks to the angular 2 DI mechanism.

Upvotes: 2

Related Questions