DEV Community

Henri de la Hoz
Henri de la Hoz

Posted on

HTTP Requests in Angular

HTTP Requests

Angular provides its own module to process http request.
In order to use it, we must import the HttpClientModule module from the app.module.ts file, then from the service or module we plan to use the http module we must import the service HttpClient.

It is important to remember that the http module of angular returns Observable objects, so in order to consume the result of the request we will need to use the method subscribe in order to have access to the data.

  fetchProduct() {
    this.productsService.getAllProducts().subscribe((products) => {
      this.products = products;
    });
  }
Enter fullscreen mode Exit fullscreen mode

We can easily map the response from a http request by declaring the desired type next to the method name.

  getAllProducts() {
    return this.http.get<Product[]>(environment.url_api);
  }
Enter fullscreen mode Exit fullscreen mode

the previous approach can be applied in many scenarios.

GET Method

  getProduct(id: string) {
    return this.http.get<Product>(`${environment.url_api}${id}`);
  }
Enter fullscreen mode Exit fullscreen mode

POST Method

export interface Product {
  id: string;
  title: string;
  price: string;
  images: string[];
  description: string;
  category: Category;
}

export interface CreateProductDTO extends Omit<Product, 'id'. 'category'> {
  categoryId: number;
}

  createProduct(body: CreateProductDTO) {
    return this.http.post<Product>(environment.url_api, body);
  }
Enter fullscreen mode Exit fullscreen mode

PUT PATCH Methods

export interface UpdateProductDTO extends Partial<CreateProductDTO> {
}

  updateProduct(id: string, body: UpdateProductDTO) {
    return this.http.put<Product>(`${environment.url_api}${id}`, data);
  }
Enter fullscreen mode Exit fullscreen mode

DELETE Methods

  deleteProduct(id: string) {
    return this.http.delete<boolean>(`${environment.url_api}${id}`);
  }
Enter fullscreen mode Exit fullscreen mode

URL Params

  getProductsByPage(limit: number, offset: number) {
    return this.http.get<Products[]>(`${environment.url_api}`, {
      params : { limit, offset }
    });
  }
Enter fullscreen mode Exit fullscreen mode

We can also create the params programmatically using the class HttpParams as follows

  getProductsByPage(limit?: number, offset?: number) {
    let params = new HttpParams();
    if (limit && offset){
      params = params.set('limit', limit);
      params = params.set('offset', offset)
    }
    return this.http.get<Products[]>(`${environment.url_api}`, {
      params
    });
  }
Enter fullscreen mode Exit fullscreen mode

Typing HTTP Responses

We can use an interface to assign a valid data type to the response coming from an API. This is a good practice to avoid certain type problems.

As an example to show how to type HTTP response, let's give our attention to the following interface.

interface User {
  gender: string;
  email: string;
  phone: string;
}
Enter fullscreen mode Exit fullscreen mode

User interface can be use as follows

myFunction(): Observable<User[]>{
    return this.http.get("URL").pipe(
        map(
            (response:any) => response.results as User[]
            ))
}
Enter fullscreen mode Exit fullscreen mode

Handling errors

this.http.get().pipe(
  retry(3), // try again 3 times
  catchError((error: HttpErrorResponse) => {
    // error.status HttpStatusCode
    return throwError("mensaje de error");
  })
  //normal flow
);
Enter fullscreen mode Exit fullscreen mode

We use retry operator to avoid firing error immediately, instead we try 3 times and in case no success we process to call catchError operator to handle the exception.

Downloading files

getFile(){
    return this.http.get('URL.txt', {responseType:'text'})
        .subscribe(content => {})
}
Enter fullscreen mode Exit fullscreen mode

Inside subscribe method we can handle a way of open a window or any other functionality to give the use the functionality to save the file.

Interceptors

Interceptors are custom services used to add attributes to our HTTP request, like injecting tokens or add headers.

Steps to create an auth interceptor

  1. Create a service using the command. ng g s auth
  2. Rename the service to auth.interceptor.ts and refactor any instruction related with the name we just changed.
  3. Remove the line provideIn:'root' this line is going to be found inside the auth.interceptor.ts this line should be removed because we want to avoid this new service to be available all over the app but we want to limit it's use to certain scenarios.
  4. Our new interceptor class should implements HttpInterceptor
  5. Our logic is going to be implemented in the method intercept
  6. In app.module.ts we set manually our new interceptor class as a provider.
// auth.interceptor.ts
export class AuthInterceptor implements HttpInterceptor {
  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    request = request.clone({
      setHeaders: {
        myToke: "1234",
      },
    });
    return next.handle();
  }
}
Enter fullscreen mode Exit fullscreen mode
// app.module.ts
import { HTTP_INTERCEPTORS } from "@angular/common/http";
//import AuthInterceptor

providers: [
  {
    provide: HTTP_INTERCEPTORS,
    useClass: AuthInterceptor,
    multi: true,
  },
];
Enter fullscreen mode Exit fullscreen mode

Note: If we want to use interceptor to store token, it is better to use indexDb to store it rather than localStorage

If we want to store a token or some value in localStorage or any other local technology to store data we can proceed as follows.

loginRestAPI(email:string, password: string){
    return this.http.post('URL',{email, password}).pipe(tap(dat) => {
        //store in local storage or any other strategy
    });
}
Enter fullscreen mode Exit fullscreen mode

In recent versions of Angular, it is recommended that we use the command ng g interceptor auth

Top comments (0)