1

I'm new to Angular 2, so excuse me if the question is silly.

I have to fetch data from the server and display it in the component. The server has some API methods, so I've created the api.service.ts which looks like this:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

const protocol = 'http';
const domain = 'mydomain.ng';
const port = ':4200';

@Injectable()
export class ApiService {

  constructor(private http: HttpClient) { }

  buildQuery(apiMethod: string) {
    return `${protocol}://${domain}${port}/${apiMethod}`;
  }

  get(apiMethod: string): Observable<Response> {

    const query = this.buildQuery(apiMethod);

    return this.http.get<Response>(query)
    .map(
      resp => {
        if (resp.ok) {
          return resp;
        } else { // Server returned an error
          // here I need to show UI error in the component
        }
      }
    )
    .catch( // Error is on the client side
      err => {
        // here I need to show UI error in the component
      }
    );
  }

  getGeneralReport(): Observable<Response> {
    return this.get('generalReport');
  }
}

Server API has a lot of methods, so the get() method is designed to perform the actual request and handle common mistakes. Then I will have methods like getGeneralReport() which will call the get method with the parameter specifying which API method should be used.

Also I have a component called general.component.ts where the api.service is injected:

import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../shared/api/api.service';

@Component({
  selector: 'app-general',
  templateUrl: './general.component.html',
  styleUrls: ['./general.component.scss']
})
export class GeneralComponent implements OnInit {

  generalInfo: Response;

  constructor(private apiService: ApiService) { }

  ngOnInit() {
    this.apiService.getGeneralReport().subscribe(
      data => {
        this.generalInfo = data;
        // Display the received data
      }
    );
  }

}

There will be more components like general.component which will use the api.service. Now I'm stuck because I need to pop up the UI window in all the components which use api.service if the error occurs in api.service. Is it possible or should I use some different approach?

1 Answer 1

2

Yes it is possible, do it like this:

this.apiService.getGeneralReport().subscribe(
  data => {
    this.generalInfo = data;
    // Display the received data
  }, 
   err => {
      // yourPopupmethod(err)
   }
);

and in service throw error. So update your service by adding HandleError method:

handleError(error: Response | any) {
     return Observable.throw(new Error(error.status))
}

  get(apiMethod: string): Observable<Response> {

    const query = this.buildQuery(apiMethod);

    return this.http.get<Response>(query)
       .map(
           resp => {
              if (resp.ok) {
                 return resp;
              } else { // Server returned an error
                 this.handleError(resp);
                }
           }
         )
       .catch(
          err => {
             this.handleError(err);
          }
      );
    }
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the answer. But since I will have a lot of components, which will make use of the api.service, I need to place all the error handling code into the service in order to avoid code duplication. Is this possible?
By the way if (resp.ok) { return resp; } else { } is incorrect way to check if server returned error
If it sends status other that 200 , it will be caught by catch block
Yeah, my bad, thank you. Now, looking on your answer to the question, it is almost what I wanted. But is it possible now to avoid writing // yourPopupmethod(err) in all the components? Or this can be also done from the service? For example if I pass to the service constructor the reference of the component?
@NikitaMarinosyan brat ofcource it is possible, but not the way you are thinking. You should create some kind of NotificationService which has for example method notifyError(text) which makes a notification. Then you should inject it in components which can have errors, and whenever you got error you call notificationService.notifyError(errortext).

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.