1

I am building an angular2 app. I have a global service called HttpClient which is handling all requests before angulars builtin http service gets fired. Also this service handles all my response errors by checking the status codes:

import { Injectable } from '@angular/core';
import { Headers, Http, Response, } from '@angular/http';

import { MessageProvider } from '../../providers/message/message.provider'

@Injectable()
export class HttpClient {

    private webApi = 'http://localhost:8080/api/v1/';

    constructor(
        private http: Http,
        private messageProvider: MessageProvider) { }

    get(url: string): Promise<Response> {
        return this.http.get(this.webApi + url, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    post(url: string, data: Object): Promise<Response> {
        return this.http.post(this.webApi + url, data, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    put(url: string, data: Object): Promise<Response> {
        return this.http.put(this.webApi + url, data, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    delete(url: string): Promise<Response> {
        return this.http.delete(this.webApi + url, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    private handleError (error: any) {

        var status: number = error.status;

        if(status == 401) {
            this.messageProvider.setMessage(error);
            this.messageProvider.message.text = "You have to be logged in to reach this page.";
        }


        let errMsg = (error.message)
            ? error.message
            : status
                ? `${status} - ${error.statusText}`
                : 'Server error';

        console.error(errMsg); // log to console instead

        return error;
    }

    private createAuthorizationHeader() {

        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        headers.append('Accept', 'application/json');

        if (localStorage.getItem('token'))
            headers.append('Authorization', 'Bearer ' + localStorage.getItem('token'));

        return headers;
    }
}

Now, lets pretend the calling component was about login:

import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';

import { Login } from '../../core/classes/login/login'

import { AuthenticationProvider } from '../../providers/authentication/authentication.provider'
import { MessageProvider } from '../../providers/message/message.provider'

@Component({
  selector: 'my-login',
  templateUrl: 'app/components/login/login.component.html'
})
export class LoginComponent implements OnInit, OnDestroy {

  @Input() login: Login;
  error: any;

  constructor(
    private authProvider: AuthenticationProvider,
    private route: Router,
    private messageProvider: MessageProvider) { }

  ngOnInit() {
    this.login = new Login();
  }

  ngOnDestroy() {
    this.messageProvider.setDefault();
  }

  onSubmit() {
    this.authProvider.login(this.login)
        .then(auth => {
            if (this.authProvider.isAdmin())
                this.route.navigateByUrl('admin/users');

            else if (this.authProvider.isLoggedIn())
                this.route.navigateByUrl('/');
            })
            .catch(error => {console.log(error);});
  }
}

In this case I don't want the error from the HttpClient ("You have to be logged in to reach this page.") but a more customized message like "No user found". I know that I could do something like the following but there is no error anymore:

onSubmit() {
    this.authProvider
        .login(this.login)
        .then(auth => {
            if (this.authProvider.isAdmin())
                this.route.navigateByUrl('admin/users');

            else if (this.authProvider.isLoggedIn())
                this.route.navigateByUrl('/');
            })
            .catch(error => {
                var status: number = error.status;

                if(status == 401) {
                    this.messageProvider.setMessage(error);
                    this.messageProvider.message.text = "No user found.";
                }
            });
}

So is there a way to maybe cause another error in the catch() function within the HttpClient? So I can handle the error again in my LoginComponent.

1 Answer 1

3

I think you can throw in the catch method to essentially "map" your error. If you want to also update your messageProvider then you could do...

.catch(error => {
    var status: number = error.status;
    var newError = {};
    if(status == 401) {
        this.messageProvider.setMessage(error);
        this.messageProvider.message.text = "No user found.";
        newError.errorMessage = "No user found.";
    }
    throw newError;
});

Confirmed with this example:

  var obs = Observable.of(12);
  obs.map((value) => {
    throw "blah";
  }).catch((error) => {
    if(error === "blah") {
      throw "baz";
    } else {
     return Observable.of("Hello");
    }
  }).subscribe((value) => {
    console.log("GOOD: " + value);
  }, (error) => {
    console.log("ERR: " + error);
  });
  //Logs ERR: baz
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.