Utilizando o Resource API do Angular 19 em um pequeno buscador
A API Resource, lançada no Angular 19, integra-se aos Signals, permitindo que componentes reajam automaticamente a mudanças nos dados. Isso elimina a necessidade de gerenciar assinaturas de observables ou usar outras soluções complexas. Veja neste texto um exemplo prático aplicado a um buscador.
Ainda em modo experimental, o Resource lançado no Angular 19, tem o objetivo de efetuar operações de leitura, reagindo a mudanças de estado de um ou mais signals. Antes desse lançamento, a abordagem mais comum era utilizar o effect para monitorar alterações em signals e, em seguida, chamar uma função para realizar uma consulta, como uma requisição a uma API. O Resource simplifica bastante esse processo e será o foco deste texto.
Note that resource is intended for read operations, not operations which perform mutations. resource will cancel in-progress loads via the AbortSignal when destroyed or when a new request object becomes available, which could prematurely abort mutations.
Para testar esse novo recurso, criei um pequeno e simples buscador. A ideia é que conforme o usuário digite, vamos alterando o valor de um signal e essa mudança dispare uma nova requisição à uma API. Consequentemente, o resultado da consulta é exibido na tela.
Construção do cenário de estudo
Para criar o cenário de estudo, utilizei dois projetos:
frontend: um projeto Angular (versão 19)
backend: uma pequena API com Node.js, sem frameworks.
Criando o projeto Angular
Para criar o projeto Angular, utilizei o seguinte comando e opções:
ng new --skip-git --skip-tests teste_resource
✔ Which stylesheet format would you like to use? Sass (SCSS)
[https://sass-lang.com/documentation/syntax#scss]
✔ Do you want to enable Server-Side Rendering (SSR) and
Static Site Generation (SSG/Prerendering)? No
Após criar o projeto, instalei o pacote Angular Material para ter acesso a uma ampla variedade de componentes visuais. Este pacote não é obrigatório para o uso do resource!
# Acessando o diretório do projeto criado
cd teste_resource
# Adicionando o Angular Material
ng add @angular/material
Criando API para testes
Após criar o projeto Angular com os comandos acima, criei um diretório chamado /server e adicionei dois arquivos que irão compor a pequena API:
💡
O diretório /server pode ficar em qualquer pasta de sua preferência. Não precisa necessariamente ficar no mesmo nível de diretório do projeto Angular.
Abaixo o arquivo JSON que é utilizado no código acima:
Essa API de testes está preparada para receber requisições no seguinte formato:
# Pesquisa os carros que começam com "ford"
curl -i "http://localhost:3000?q=ford"
Resultado:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
[{"id":3,"nome":"Ford Mustang","descricao":"Clássico muscle car americano com potência impressionante."},{"id":16,"nome":"Ford Fusion","descricao":"Modelo híbrido com conforto e eficiência."},{"id":21,"nome":"Ford Explorer","descricao":"SUV médio com bastante espaço."},{"id":24,"nome":"Ford F-150","descricao":"Picape clássica com recursos modernos."},{"id":43,"nome":"Ford Edge","descricao":"Crossover com desempenho confiável."}]%
💡
No código acima, foi introduzido intencionalmente um atraso de 1 segundo em cada requisição. Esse atraso tem como objetivo permitir o estudo detalhado do comportamento do abortSignal, que será explicado posteriormente.
Agora que a pequena API de testes foi criada, seguimos com foco no projeto Angular.
Preparando o projeto Angular
Sem entrar nos detalhes, a seguir fiz algumas inclusões e alterações no projeto Angular. A ideia foi criar os arquivos necessários, ajustar o estilo visual e efetuar as devidas referências, veja a seguir:
Criando os recursos com Angular CLI:
# Cria o componente <app-buscador>
ng g c buscador
# Cria a interface Carro
ng g i carro
Conteúdo dos arquivos modificados e/ou recém criados:
Utilizando o resource para efetuar uma consulta
O mecanismo de busca implementado a seguir funciona da seguinte forma: o usuário digita a palavra desejada em um campo de texto exibido na tela. Assim que o texto inserido atingir pelo menos 3 caracteres, o valor digitado será atribuído a uma variável do tipo WritableSignal. Essa variável, ao ser modificada, dispara a execução da loader, associada ao resource.
Na implementação abaixo deixei vários comentários para facilitar o entendimento. Também incluí um tratamento de erro com o SnackBar do Angular Material.
Resultado:
Uso do abortSignal
Em um post mais antigo, comentei sobre o uso do AbortController para aplicar timeouts ou cancelar requisições.
No caso do resource, sempre que o valor retornado pela request (declarado dentro do resource) é alterado, ele executa novamente o loader. Nesse cenário, o abortSignal é utilizado para que o resource cancele a execução anterior, caso ela ainda esteja em andamento, antes de iniciar uma nova. Abaixo, observe o comportamento das requisições sem o uso do abortSignal e com ele:
Observe acima que, à medida que o usuário digita pausadamente, várias requisições são disparadas sem que nenhuma delas seja cancelada. Por outro lado, ao utilizar o abortSignal, à medida que o usuário digita pausadamente, a requisição anterior é cancelada caso ainda esteja em andamento:
Considerações
Ainda em modo experimental, dependendo da resposta da comunidade e do time de desenvolvimento do Angular, pode ser que essa funcionalidade seja alterada. Então use com cuidado enquanto estiver em modo experimental.
A capacidade de reatividade do signal é incrível. Até então, tínhamos que "escutar" por alterações de valores e então iniciar o fluxo para obter dados externos, como de uma API. O resource claramente simplificou esse processo, além da capacidade de cancelar requisições pendentes através do abortSignal, que é um diferencial importante, evitando problemas comuns em aplicações que lidam com múltiplas requisições.