No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Manejo de errores

13/23
Recursos

Las peticiones HTTP que tu aplicación realiza pueden fallar por una u otra razón. Recuerda que una aplicación profesional tiene que contemplar estos escenarios y estar preparada para cuando esto suceda.

Manejo de Errores con RxJS

Ya hemos visto anteriormente la función retry() de RxJS para reintentar una petición en caso de fallo. Pero si el error persiste, veamos cómo es posible manejar los mismos.

1. Imports desde RxJS

Presta atención a las siguientes importaciones desde RxJS y @angular/common/http que utilizaremos.

// service/api.service.ts
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
    // ...
}

2. Manejo de errores con catchError()

Agrega a los métodos que realizan las solicitudes HTTP un .pipe() para manipular los datos que el observable emita antes de enviarlos al componente.
Aquí estamos utilizando catchError de RxJS para capturar los errores y le pasamos un método personalizado llamado handleErrors() para centralizar el manejo de los mismos (Así no repetimos el mismo código en todos los pipes).

// service/api.service.ts
getProduct(idProduct: number): Observable<Product> {
  return this.http.get<Product>(`https://example.com/api/productos/${idProduct}`)
    .pipe(
      catchError((err: HttpErrorResponse) => {
        return this.handleErrors(err)
      })
    );
}
  
handleErrors(error: HttpErrorResponse): Observable<never>  {
  if (error.status == HttpStatusCode.Forbidden)
    return throwError('No tiene permisos para realizar la solicitud.');
  if (error.status == HttpStatusCode.NotFound)
    return throwError('El producto no existe.');
  if (error.status == HttpStatusCode.InternalServerError)
    return throwError('Error en el servidor.');
  return throwError('Un error inesperado ha ocurrido.');
}

3. Identifica el tipo de error

Dicho método recibe un parámetro del tipo HttpErrorResponse que Angular nos provee para tipar errores HTTP. Utilizando el enumerado HttpStatusCode puedes determinar qué tipo de error se produjo. Si fue un error 403, 404, 500, etc. Fácilmente, puedes verificarlo y devolver un error al componente con throwError y un mensaje personalizado.

NOTA: Más allá de este enum que Angular nos facilita, es muy importante que como desarrollador de software sepas diferenciar lo que significa un 401, 403, 404, 500, 501, entre otros estados HTTP. Poco a poco lo irás aprendiendo.

4. Captura los errores en los componentes

En tu componente, captura los errores en las suscripciones de la siguiente manera:

// components/catalogo/catalogo.component.ts
this.apiService.getProducts()
  .subscribe(res => {
    this.productos = res;
  }, err => {
    alert(err);     // Aquí se emitirá el alerta con el mensaje que `throwError` devuelva.
  });

Así, ya puedes diferenciar los errores y comunicarle al usuario si algo salió mal de la manera más apropiada, mostrándole un mensaje o una alerta.


Contribución creada por: Kevin Fiorentino.

Aportes 7

Preguntas 2

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Para no mostrar una alerta podríamos utilizar aviso de una librería llamada SweetAlert2.

Debemos instalar

Lo importamos dentro del componente

Dentro del método lo activamos

Hay varios tipos de alertas que podemos utilizar y customizar dentro de la documentación de la librería lo informa.

https://sweetalert2.github.io/#examples

Amigos, la forma del suscribe sale deprecado (aunque igual funciona), revisando la documentación se podría hacer así:

Y yo creando la interfáz para el error, y para los estados validando el numerito, teniendo tantas cosas en Angular para ello. Que gran clase. Gracias 😄

Excelente clase! Poco manejo los errores, por lo que esta clase me encanto y tengo mejor manejo de los mismos. Caso curioso de acuerdo a mi experiencia, pocos manejan los errores, es común que eso lo haga el backend. Ya hoy por hoy porque se la codificación de los errores y los puedo solucionar en menor tiempo, pero ciertamente, como Front-End si estamos dedicados a desarrollar del lado del cliente, debemos manejar estos errores para tener un desarrollo más limpio y una mejor administración de los errores para la pronta solución de los mismos.

si les sale el throwError en deprecated es porque ahora se utiliza de esta manera

En throwError no es necesario retornar un new Error('Nuestro error '), seria de la siguiente manera:

/**
   * Manejo de errores
   */
  erroreHttp(e: HttpErrorResponse) {
    if (e.status === HttpStatusCode.NotFound) {
      return throwError(() => ("Ups producto no esta encontrado"));
    }
    return throwError(() => "Ups algo esta fallando"));
  }

Con el manejo de observables debemos ver como es el manejo de errores

Se puede obtener un manejo de errores desde el servicio para el manejo de excepciones en el backend

product.service.ts


import { HttpClient, HttpParams, HttpErrorResponse, HttpStatusCode } from '@angular/common/http';

import { retry, catchError } from 'rxjs/operators';

import { throwError } from 'rxjs';




getProduct(id: number) {

	 return this.http.get<Product>(`${this.apiUrl}/${id}`)

	 .pipe(

		 catchError((error: HttpErrorResponse) => {

		 switch(error.status) {
	
		 case HttpStatusCode.Conflict:

			return throwError(() => new Error ('Ups algo esta fallando en el server'));

		 case HttpStatusCode.NotFound:

			 return throwError(() => new Error ('El producto no existe'));

		 default:

			 return throwError(() => new Error ('Ups algo salio mal'));
	
			 }

		 })

	 )

 }

Tambien se puede hacer manejo de errores desde el front end, utilizano la libreria sweetalert2
sweetalert2
sweetalert2 Github

Lo primero es importar la sweetalert2 en nuestro app.module.ts

app.module.ts

import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2';

@NgModule({

	imports: [
		SweetAlert2Module
	],
})


despues activamos el manejo de errores con sweetalert2 en nuestro products.component

products.component.ts


import Swal from 'sweetalert2';

export class ProductsComponent implements OnInit {
 statusDetail: 'loading' | 'success' | 'error' | 'init' = 'init';
}


onShowDetail(id: number) {

 this.statusDetail = 'loading';

 this.productsService.getProduct(id)

 .subscribe({

	 next: (d) => this.showDetailOk(d),

	 error: (e) => this.showDetailError(e),

	 complete: () => console.info('complete')

	 });

 }

  

 showDetailOk(data: Product) {

	 this.statusDetail = 'success';

	 console.log('producto obtenido: ', data);

	 this.toggleProductDetail();

	 this.productChosen = data;

 }

  

 showDetailError(e: any) {

	 this.statusDetail = 'error';

	 this.toggleProductDetail();

	 Swal.fire({

		 title: 'Error!',

		 text: e,

		 icon: 'error',

		 confirmButtonText: 'Ok',

	 });

 }