ngx-rx-request-resource
v1.0.11
Published
Uma API reativa para requisições HTTP em Angular usando RxJS e Signals.
Maintainers
Readme
ngx-rx-request-resource
Versão 1.0.11
Uma API reativa para requisições HTTP em Angular, utilizando o poder do RxJS e a simplicidade dos Signals.
🕹️ Live Demo
You can interact with a live example of the library here:
✨ Destaques
Abordagem Híbrida: Combine o fluxo reativo do RxJS com o sistema de reatividade de Signals do Angular.
Controle de Concorrência: Gerencie requisições com
switchMap(para consultas) eexhaustMap(para mutações) para evitar condições de corrida.Tipagem Segura: Garante que os dados de entrada e saída estejam sempre tipados corretamente, reduzindo erros em tempo de execução.
API Declarativa e Imperativa: Escolha entre acionar requisições de forma reativa (a partir de Signals) ou imperativa (a partir de eventos de clique).
Pré-processamento Flexível: Utilize operadores do RxJS como
debounceTimeoufilterpara controlar o fluxo de dados antes da chamada à API.Callbacks de Mutação (Opcional): Execute ações de sucesso ou falha de forma limpa e tipada após uma requisição imperativa.
Método reload() [NOVO]: Re-execute a última requisição com os mesmos parâmetros, ideal para botões de "Tentar Novamente/Atualizar/Reprocessar".
Exemplo Interativo: Experimente a demo no StackBlitz!
Peer dependencies:
Angular 20+
RxJS 7+
🚀 Instalação
Instale a biblioteca via npm:
npm install @ngx-rx-request-resource
🔹 Conceitos Principais
| Conceito | Descrição |
| --------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `ResourceState<T>` | Estado de uma requisição (`idle`, `loading`, `success`, `error`). |
| `Resource<T>` | Interface que encapsula estado reativo com Signals: `value`, `status`, `isLoading`, `error`, `source`. |
| `HighOrderOperatorType` | Tipo do operador RxJS para controlar concorrência: `switchMap` (queries) ou `exhaustMap` (mutations). |
| `createRequestResource` | Cria uma Resource acionável imperativamente (mutations). |
| `createRequestResourceFromSignal` | Cria uma Resource reativa ligada a um Signal (queries). |
| `withConfirm` | Operador auxiliar para pré-confirmação de mutações. |
| `Callbacks de Mutação` | Execute ações no sucesso ou falha da requisição. Opcional |
🔹 Resource State
idle → ainda não houve requisição
loading → requisição em progresso
success → requisição finalizada com sucesso
error → requisição falhou
📖 Guia de Uso
Criando uma Requisição a partir de um Evento (Gatilho Imperativo)
Use createRequestResource para disparar uma requisição em resposta a um evento, como o clique de um botão. É ideal para mutações (POST, PUT, DELETE).
1. No seu serviço:
// services/user.service.ts
import { createRequestResource } from '@ngx-rx-request-resource';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
interface User { id: number; name: string; }
@Injectable({ providedIn: 'root' })
export class UserService {
constructor(private http: HttpClient) {}
readonly createUser = createRequestResource<User, User>(
(user) => this.http.post<User>('https://api.meusite.com/users', user),
{ operatorType: 'exhaustMap' } // Usa exhaustMap para evitar cliques duplos
);
}
2. No seu componente:
// components/user-form.component.ts
import { Component } from '@angular/core';
import { UserService } from './user.service';
import { User } from './user.model';
@Component({
selector: 'app-user-form',
template: `
<button (click)="submit()">
Salvar Usuário
</button>
<div *ngIf="userService.createUser.isLoading()">Salvando...</div>
`
})
export class UserFormComponent {
constructor(public userService: UserService) {}
submit() {
const newUser: User = { id: 0, name: 'João' };
this.userService.createUser.execute(newUser);
ou
//callbacks Opcionais
this.userService.createUser.execute(newUser,
{
onSuccess: (data) => console.log('Usuário criado com sucesso:', data),
onError: (err) => console.error('Erro ao criar usuário:', err)
};
);
}
}
Criando uma Requisição a partir de um Signal (Gatilho Reativo)
Use createRequestResourceFromSignal para acionar uma requisição sempre que um Signal de origem muda. É ideal para consultas (GET), como em um campo de busca.
1. No seu serviço:
// services/product.service.ts
import { createRequestResourceFromSignal } from '@ngx-rx-request-resource';
import { HttpClient } from '@angular/common/http';
import { Injectable, signal } from '@angular/core';
import { debounceTime } from 'rxjs/operators';
interface Product { id: string; name: string; }
@Injectable({ providedIn: 'root' })
export class ProductService {
constructor(private http: HttpClient) {}
readonly searchQuery = signal('');
readonly searchResults = createRequestResourceFromSignal(
this.searchQuery,
(query) => this.http.get<Product[]>(`https://api.meusite.com/products?q=${query}`),
{
operatorType: 'switchMap',
pipeFlowPre: debounceTime(300) // Aguarda 300ms antes de disparar a busca
}
);
}
2. No seu componente:
// components/product-search.component.ts
import { Component } from '@angular/core';
import { ProductService } from './product.service';
@Component({
selector: 'app-product-search',
template: `
<input [(ngModel)]="searchQuery" placeholder="Buscar produtos...">
@if(productService.searchResults.isLoading()) {
<p>Carregando...</p>
} @else if (productService.searchResults.value(); let products) {
@if (products.length > 0) {
<ul>
@for (product of products; track product.id) {
<li>{{ product.name }}</li>
}
</ul>
} @else {
<p>Nenhum produto encontrado.</p>
}
}
`
})
export class ProductSearchComponent {
constructor(public productService: ProductService) {}
searchQuery = this.productService.searchQuery;
}
🔹 Pré-processamento / Confirmação antes de mutações
import { withConfirm } from '@ngx-rx-request-resource';
import { of } from 'rxjs';
const deleteUserResource = createRequestResource(
(userId: number) => this.http.delete(`/api/users/${userId}`),
{
operatorType: 'exhaustMap',
pipeFlowPre: withConfirm((id) => {
// Retorna um Observable<boolean> que indica se deve continuar
return confirmDialog(`Deseja deletar o usuário ${id}?`);
}),
}
);
// Executando
deleteUserResource.execute(123);
🔹 Benefícios
Evita duplicação de lógica de loading e tratamento de erro.
Código declarativo e reativo.
Suporte nativo a Angular Signals.
Suporte a mutações com confirmações interativas.
Tipagem completa com TypeScript.
-------------------------------------------------------------------------------------------------------------------------------
👨💻 Autor
Moisés Neto Silva Santos
e-mail: [email protected]