Tratando erros em Angular
Ao trabalhar com redes e requisições HTTP, é comum ocorrerem erros, como quando a rede fica indisponível durante uma requisição, um endereço incorreto é fornecido e, consequentemente, o recurso não é encontrado, ou o acesso ao recurso é restrito, entre outros problemas. A interceptação de erros permite identificar o problema e tratá-lo de alguma forma, como exibindo uma mensagem de erro ao usuário.
Para capturar os erros que podem ocorrer ao fazer uma requisição, podemos usar a função catchError(). Vamos usar o código de serviço da seção anterior e adicionar o tratamento de erros:
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { User } from "./user";
import { Observable } from "rxjs";
import { map, catchError } from "rxjs/operators";
@Injectable()
export class HttpService {
  errorMessage: String = "";
  constructor(private http: HttpClient) {}
  getUsers(): Observable<User[]> {
    return this.http.get("assets/users.json").pipe(
      map((data: any) => {
        let usersList = data["userList"];
        return usersList.map(function (user: any): User {
          return new User(user.userName, user.userAge);
        });
      }),
      catchError((err) => {
        console.log(err);
        this.errorMessage = err.message;
        return [];
      })
    );
  }
}Primeiramente, no serviço, definimos a variável errorMessage, que armazenará as informações sobre o erro.
Para simular um erro, passamos um endereço incorreto "users.json" para o cliente HTTP. O tratamento de erros é feito através do método pipe(), onde a função catchError() é usada como o segundo parâmetro para capturar erros:
catchError((err) => {
  console.log(err);
  this.errorMessage = err.message;
  return [];
});A função catchError() recebe como parâmetro uma função que, por sua vez, aceita um objeto de erro lançado durante a execução da requisição. Dessa forma, podemos obter o erro e tratá-lo.
O erro em si é um objeto do qual podemos extrair várias informações. Por exemplo, a propriedade message nos dá a mensagem de erro, enquanto a propriedade status indica o código de status da resposta.
No exemplo acima, o tratamento do erro consiste em exibir o objeto no console e atribuir a mensagem de erro à propriedade errorMessage do serviço (se a requisição for bem-sucedida, esse campo receberá uma string vazia).
Vale destacar que, na função de tratamento de erros, ainda é necessário retornar um objeto Observable. Para isso, retornamos um array vazio:
return [];Assim, será criado um objeto Observable<User[]> que conterá um array vazio de objetos User.
Vamos utilizar o serviço e modificar o código do componente AppComponent:
import { Component, OnInit } from "@angular/core";
import { HttpService } from "./http.service";
import { User } from "./user";
@Component({
  selector: "my-app",
  standalone: true,
  imports: [],
  template: `<div>{{ this.httpService.errorMessage }}</div>
    <ul>
      @for(user of users; track $index){
      <li>{{ user?.name }} ({{ user?.age }})</li>
      }
    </ul>`,
  providers: [HttpService],
})
export class AppComponent implements OnInit {
  users: User[] = [];
  constructor(public httpService: HttpService) {}
  ngOnInit() {
    this.httpService.getUsers().subscribe({
      next: (data: User[]) => (this.users = data),
    });
  }
}Usando o método subscribe(), o componente pode obter um array de objetos User do serviço. Se ocorrer um erro, o array será vazio.
Para exibir informações sobre o erro, o componente acessa a propriedade errorMessage do serviço e exibe seu valor no template HTML.
Por exemplo, ao tentar acessar um arquivo JSON inexistente, a seguinte mensagem de erro será exibida:

Este é um exemplo básico de tratamento de erros, que demonstra o princípio geral. Obviamente, podemos definir outras mensagens de erro ou lidar com os erros de outras maneiras dentro do serviço.