Search code examples
angularangular7angular2-services

How to manage API function call services in Angular 7


I finished an Angular 7 web app (Roughly). As an example, I have a documents.service.ts file and it includes below HTTP GET request function:

public sendOnlyCoverPage(strProNo: string, strEstesFileName: string): Observable<any> {
    return this._http.get(this.FilesApi + "/GetSendOnlyCoverPage?strProNo=" + strProNo + '&strEstesFileName=' + strEstesFileName, httpOptions);
}

And POST request is like below format:

public FTP_PutFile(ftpModel: any): Observable<any> {
    var obj = JSON.stringify(ftpModel);
    return this._http.post(this.FilesApi + "/PostFTP_PutFile", obj, httpOptions);
}

I have two questions:

Question 1:

I have a lot HTTP GET and POST functions in different services such as above. I feel like I am doing something wrong about API function design because when I open any serivce file, there are a lot functions like above. I am thinking that is there any way to centralize these api functions. Such as I can create a middle service and whenever I need to make an API call, I can pass function name, url and parameter etc.

Question 2:

As the code shows above, I have parameter ftpModel: any. I understand it is better to create a object mapping (interface) to replace the any type. BUT again, there are a lot parameters like this one. Is there any solution for that instead of creating each object mapping (interface) for each parameter?


Solution

  • Question 1 You should create a abstract BaseService, something like this:

    import {HttpClient} from '@angular/common/http';
    import {Observable} from 'rxjs';
    import {environment} from '../../environments/environment';
    
    export abstract class BaseService<T> {
      private endpoint: string;
    
      constructor(protected http: HttpClient,
                  endpoint: string) {
        this.endpoint = endpoint;
      }
    
      findAll(): Observable<T[]> {
        return this.http.get<T[]>(this.getUrl());
      }
    
      findOne(id: number): Observable<T> {
        return this.http.get<T>(`${this.getUrl()}/${id}`);
      }
    
      save(objeto: T): Observable<T> {
        return this.http.post<T>(this.getUrl(), objeto);
      }
    
      delete(id: number): Observable<void> {
        return this.http.delete<void>(`${this.getUrl()}/${id}`);
      }
    
      protected getUrl(): string {
        return `${environment.api_url}${this.endpoint}`;
      }
    
      complete(query: string): Observable<T[]> {
        return this.http.get<T[]>(`${this.getUrl()}/complete?query=${query}`);
      }
    
    }
    

    And also, extends it in your services:

    export class ProductService extends BaseService<Product> {
    
      constructor(protected http: HttpClient) {
        super(http, 'product');
      }
    }
    

    A example in My github

    Question 2 The better approach still is what you mentioned, create your classes/interfaces for mapping.