🧩 Exercícios Práticos: Interoperabilidade entre Signals e RxJS (toSignal, toObservable)

Spec Frontend Com Angular • Trilha Progressiva em 4 Níveis


🧭 Navegação Pedagógica


🎯 Nível 1: Fundamentos

Problema 12.1 — Conversão de Observable para Signal com toSignal()

Contexto: Conversão de Observable para Signal com toSignal() no contexto de Interoperabilidade entre Signals e RxJS (toSignal, toObservable).

Requisitos de Execução:

  1. Converter stream de dados HTTP produtos$ em um Signal reativo produtos = toSignal(produtos$, { initialValue: [] }).

Resultado Esperado

Observable transformado em Signal reativo síncrono.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_12_1_SeuNome
  2. Envie na tarefa: Atividade Cap 12 - Interoperabilidade entre Signals e RxJS (toSignal, toObservable)
🔑 Gabarito de Código & Solução Comentada
// to-signal-demo.component.ts
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { toSignal } from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-to-signal-demo',
  standalone: true,
  template: `<div>Total: {{ produtos().length }}</div>`
})
export class ToSignalDemoComponent {
  private http = inject(HttpClient);
  produtos = toSignal(this.http.get<any[]>('/api/produtos'), { initialValue: [] });
}

🔍 Nível 2: Prática

Problema 12.2 — Conversão de Signal para Observable com toObservable()

Contexto: Conversão de Signal para Observable com toObservable() no contexto de Interoperabilidade entre Signals e RxJS (toSignal, toObservable).

Requisitos de Execução:

  1. Converter signal de busca filtro = signal('') em observable para aplicar operadores de debounce do RxJS.

Resultado Esperado

Signal transformado em stream RxJS para tratamento com operadores assíncronos.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_12_2_SeuNome
  2. Envie na tarefa: Atividade Cap 12 - Interoperabilidade entre Signals e RxJS (toSignal, toObservable)
🔑 Gabarito de Código & Solução Comentada
// to-observable-demo.component.ts
import { Component, signal, inject } from '@angular/core';
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
import { debounceTime, switchMap } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-interop-search',
  standalone: true,
  template: `<input (input)="onInput($event)" />`
})
export class InteropSearchComponent {
  private http = inject(HttpClient);
  busca = signal('');
  
  resultados = toSignal(
    toObservable(this.busca).pipe(
      debounceTime(300),
      switchMap(q => this.http.get<string[]>(`/api/busca?q=${q}`))
    ),
    { initialValue: [] }
  );

  onInput(e: any) { this.busca.set(e.target.value); }
}

⚡ Nível 3: Integração

Problema 12.3 — Tratamento de Erros e Rejeições no toSignal()

Contexto: Tratamento de Erros e Rejeições no toSignal() no contexto de Interoperabilidade entre Signals e RxJS (toSignal, toObservable).

Requisitos de Execução:

  1. Configurar rejectErrors: false capturando exceções do stream sem quebrar a reatividade do template.

Resultado Esperado

Signal mantendo estabilidade visual em caso de erro na stream original.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_12_3_SeuNome
  2. Envie na tarefa: Atividade Cap 12 - Interoperabilidade entre Signals e RxJS (toSignal, toObservable)
🔑 Gabarito de Código & Solução Comentada
// Implementação de referência para o requisito do nível
// safe-to-signal.ts
import { toSignal } from '@angular/core/rxjs-interop';
import { of } from 'rxjs';

export const dadoSeguro = toSignal(of('OK'), { rejectErrors: false });
// Conclusão da operação e validação de conformidade
const statusConcluido = true;
console.log('Validação de execução concluída');
if (!statusConcluido) throw new Error('Falha');

🏆 Nível 4: Desafio Corporativo

Problema 12.4 — Arquitetura Híbrida: Signals na UI e RxJS na Camada de Transporte

Contexto: Arquitetura Híbrida: Signals na UI e RxJS na Camada de Transporte no contexto de Interoperabilidade entre Signals e RxJS (toSignal, toObservable).

Requisitos de Execução:

  1. Estruturar aplicação mantendo services com RxJS/HttpClient e componentes consumindo apenas Signals.

Resultado Esperado

Padrão arquitetural corporativo recomendado pelo time do Angular homologado.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_12_4_SeuNome
  2. Envie na tarefa: Atividade Cap 12 - Interoperabilidade entre Signals e RxJS (toSignal, toObservable)
🔑 Gabarito de Código & Solução Comentada
// hybrid-architecture.service.ts
import { Injectable, inject, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { toSignal } from '@angular/core/rxjs-interop';
import { Observable, tap } from 'rxjs';

export interface Produto { id: number; nome: string; preco: number; }

@Injectable({ providedIn: 'root' })
export class CatalogoService {
  private http = inject(HttpClient);
  private endpoint = '/api/v1/catalogo';

  // Camada de transporte com RxJS Observables
  obterCatalogo$(): Observable<Produto[]> {
    return this.http.get<Produto[]>(this.endpoint).pipe(
      tap(itens => console.log(`[HTTP] ${itens.length} produtos carregados`))
    );
  }

  // Interoperabilidade: Estado em Signals para consumo direto na UI
  catalogoSignal = toSignal(this.obterCatalogo$(), { initialValue: [] });
}

⬅️ Voltar ao Índice de Exercícios 📚 Sumário de Tópicos