Observable e a biblioteca RxJS em Angular
Os métodos da classe HttpClient, após a execução de uma solicitação, retornam um objeto Observable<any>, que é definido na biblioteca RxJS ("Reactive Extensions"). Embora não faça parte do Angular diretamente, essa biblioteca é amplamente utilizada, especialmente ao interagir com o servidor via HTTP. A RxJS implementa o padrão "observador assíncrono" (asynchronous observable), permitindo que as solicitações feitas ao servidor com a classe HttpClient sejam realizadas de forma assíncrona. Isso significa que o código não é bloqueado enquanto a solicitação é processada, o que é especialmente útil em aplicações web.
Para utilizar as funcionalidades da RxJS na sua aplicação, é necessário instalar a biblioteca. Para isso, execute o seguinte comando no terminal:
npm install rxjs
Além disso, como foi mencionado no tema anterior, é necessário importar provideHttpClient no arquivo main.ts:
import { bootstrapApplication } from "@angular/platform-browser";
import { AppComponent } from "./app/app.component";
import { provideHttpClient } from "@angular/common/http";
bootstrapApplication(AppComponent, { providers: [provideHttpClient()] }).catch(
  (err) => console.error(err)
);Ao utilizar métodos especiais para o objeto Observable, como map e filter, é possível realizar um processamento adicional dos resultados recebidos do servidor.
Por exemplo, vamos usar o projeto do tema anterior, com a seguinte estrutura:
helloapp/ ├── src/ │ ├── app/ │ │ ├── app.component.ts │ │ ├── user.ts │ ├── assets/ │ │ ├── data.json │ ├── main.ts │ ├── index.html ├── angular.json ├── package-lock.json ├── package.json └── tsconfig.json
No arquivo data.json, podemos definir os dados de forma que não correspondam diretamente ao array de objetos User:
 {
  "userList": [
      {
          "userName": "Bob",
          "userAge": 28
      },
      {
          "userName": "Tom",
          "userAge": 39
      },
      {
          "userName": "Alice",
          "userAge": 32
      }
  ]
}Como modelo de dados, usaremos a classe User, definida no arquivo user.ts:
export class User {
  constructor(public name: string, public age: number) {}
}Nesse caso, não há correspondência direta entre os nomes das propriedades: name e userName, ou age e userAge.
No arquivo http.service.ts, definimos o seguinte código para um serviço que vai obter os dados do arquivo data.json:
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { User } from "./user";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
@Injectable()
export class HttpService {
  constructor(private http: HttpClient) {}
  getUsers(): Observable<User[]> {
    return this.http.get("assets/data.json").pipe(
      map((data: any) => {
        let usersList = data["userList"];
        return usersList.map(function (user: any): User {
          return new User(user.userName, user.userAge);
        });
      })
    );
  }
}O propósito de usar um serviço especializado para lidar com HTTP é ocultar os detalhes do envio de requisições. O componente espera receber dados específicos, como uma coleção de objetos User. Com o método map da RxJS, podemos transformar os dados recebidos de um formato para outro.
Após a execução do método get(), podemos chamar o método pipe(), que permite processar os resultados da solicitação. O método pipe recebe uma função como parâmetro, que processa os dados da requisição. Nesse caso, o operador map desempenha esse papel, transformando os resultados em novos objetos.
Para usar os elementos da biblioteca RxJS, é necessário importá-los:
import { Observable } from "rxjs";
import { map } from "rxjs/operators";No final, o método getUsers() retorna um objeto Observable<User[]>.
Agora, vamos utilizar o serviço no componente da aplicação:
import { Component, OnInit } from "@angular/core";
import { HttpService } from "./http.service";
import { User } from "./user";
@Component({
  selector: "my-app",
  standalone: true,
  imports: [],
  template: `<ul>
    @for(user of users; track $index) {
    <li>{{ user?.name }} ({{ user?.age }})</li>
    }
  </ul>`,
  providers: [HttpService],
})
export class AppComponent implements OnInit {
  users: User[] = [];
  constructor(private httpService: HttpService) {}
  ngOnInit() {
    this.httpService.getUsers().subscribe({
      next: (data: User[]) => (this.users = data),
    });
  }
}Neste código, o serviço HttpService é utilizado no componente AppComponent para obter e exibir uma lista de usuários.
