Introdução

Quando trabalhamos com programação assíncrona, especialmente em frameworks como Angular ou bibliotecas como RxJS, o conceito de Observables se torna essencial. Observables oferecem uma abordagem poderosa e flexível para lidar com fluxos de dados assíncronos, como eventos do usuário, requisições HTTP e interações em tempo real.

Mas o que exatamente são os Observables? Eles podem ser comparados a um fluxo contínuo de dados que pode ser observado, permitindo que manipuladores (os “observadores”) reajam conforme os dados chegam. Diferente de soluções como funções e Promises, os Observables vão além, possibilitando a manipulação de múltiplos valores ao longo do tempo, transformações e até mesmo o cancelamento de fluxos.

Antes de mergulhar nas comparações, é importante entender o contexto no qual os Observables se destacam: as arquiteturas Pull e Push.


Arquiteturas Pull e Push: Qual a diferença?

Os Observables se destacam em sistemas de arquitetura Push, mas o que isso significa exatamente?

Arquitetura Pull

Na arquitetura Pull:

  • O consumidor é responsável por solicitar os dados ao produtor.
  • Exemplos:
    • Funções: O consumidor chama uma função e obtém um valor retornado.
    • Iteradores: O consumidor solicita explicitamente o próximo valor.

Características do Pull:

  • O consumidor tem controle total sobre quando e como os dados são obtidos.
  • O produtor só trabalha quando solicitado.
// Exemplo de Pull com uma função:
function getValue() {
return 42; // O consumidor chama a função e obtém um valor.
}
console.log(getValue());

Arquitetura Push

Na arquitetura Push:

  • O produtor envia dados ao consumidor de forma ativa, sem a necessidade de requisição explícita.
  • Exemplos:
    • Eventos (como cliques de mouse): O produtor (navegador) envia notificações ao consumidor (listener).
    • Observables: O consumidor se inscreve no fluxo de dados e o produtor empurra os valores.

Características do Push:

  • O consumidor reage aos dados conforme eles chegam, mas não controla o momento em que isso acontece.
  • Ideal para sistemas assíncronos.
// Exemplo de Push com eventos:
document.addEventListener('click', () => {
    console.log('Clique detectado!');
});

Funções, Promises e Observables: Entenda as diferenças

Os Observables têm semelhanças com funções e Promises, mas oferecem recursos que os tornam mais versáteis. Veja uma comparação detalhada:

CaracterísticaFunçõesPromisesObservables
ArquiteturaPullPushPush
N° de valoresÚnico valorÚnico valorMúltiplos valores ao longo do tempo
Eager ou Lazy?Eager (executa imediatamente)Eager (executa imediatamente)Lazy (executa somente após inscrição)
CancelamentoNão suportaNão suportaSuporta
EncadeamentoNão suportaSuporta .then()Suporta operadores como .map() e .filter()
NaturezaSíncronaAssíncronaAssíncrona

Funções

  • Descrição: Blocos de código reutilizáveis que executam tarefas específicas e retornam um valor.
  • Limitação: Lida apenas com um valor de forma síncrona e não suporta cancelamento.
function add(a, b) {
    return a + b;
}
console.log(add(3, 4)); // Retorna 7

Promises

  • Descrição: Representam a eventual conclusão (ou falha) de uma operação assíncrona.
  • Limitação: Resolvem apenas um único valor. Após resolvidas ou rejeitadas, não podem ser reutilizadas.
const promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("Dados carregados!"), 1000);
});

promise.then(data => console.log(data)); // Após 1s, exibe: "Dados carregados!"

Observables

  • Descrição: Representam fluxos de dados que podem emitir múltiplos valores ao longo do tempo. São lazy, ou seja, só começam a emitir valores quando alguém se inscreve.
  • Pontos fortes: Manipulação poderosa de fluxos de dados, suporte a cancelamento e transformação dos valores com operadores como map, filter e merge.
import { Observable } from 'rxjs';

const observable = new Observable(subscriber => {
    subscriber.next('Primeiro valor');
    setTimeout(() => subscriber.next('Segundo valor'), 1000);
    setTimeout(() => subscriber.complete(), 2000);
});

observable.subscribe({
    next: value => console.log(value), // Executa para cada valor emitido
    complete: () => console.log('Finalizado!') // Chamado ao completar
});

Quando usar Observables?

Os Observables são ideais para cenários onde:

  1. Há múltiplos valores sendo emitidos ao longo do tempo:
    • Eventos do usuário.
    • Atualizações em tempo real.
    • Requisições que emitem respostas parciais.
  2. Precisamos transformar ou combinar fluxos de dados:
    • Exemplo: Mapear cliques de botões para requisições HTTP.
  3. O cancelamento de operações é importante:
    • Exemplo: Cancelar uma busca quando o usuário digita algo diferente.

Conclusão

Os Observables são ferramentas indispensáveis em aplicações modernas, permitindo um controle avançado sobre fluxos de dados assíncronos. Embora possam parecer complexos à primeira vista, eles oferecem soluções para problemas comuns na programação reativa, como transformação de dados, manipulação de múltiplos eventos e cancelamento de tarefas.

Se você está desenvolvendo com Angular ou precisa lidar com eventos e streams complexos, investir tempo em aprender Observables é um caminho valioso!


Gostou do artigo? Compartilhe suas dúvidas ou experiências com Observables nos comentários! Vamos aprender juntos. 🚀

Categorized in:

Angular, Fundamentals,