Skip to content

exhaustMap - Ignora Nova Entrada Durante a Execução

O operador exhaustMap ignora nova entrada até que o Observable atualmente em processamento seja concluído. Isso é ideal para prevenir cliques duplicados ou múltiplas submissões de requisições.

🔰 Sintaxe Básica e Uso

ts
import { fromEvent, of } from 'rxjs';
import { exhaustMap, delay } from 'rxjs';

const clicks$ = fromEvent(document, 'click');

clicks$
  .pipe(exhaustMap(() => of('Requisição concluída').pipe(delay(1000))))
  .subscribe(console.log);

// Exemplo de saída:
// (Apenas o primeiro clique gera "Requisição concluída" após 1 segundo)
  • A entrada subsequente é ignorada até que a requisição em execução seja concluída.

🌐 Documentação Oficial RxJS - exhaustMap

💡 Padrões Típicos de Uso

  • Prevenção de múltiplos cliques em botões de envio de formulário
  • Prevenção de requisições duplas (especialmente para processos de login e pagamento)
  • Controle de exibição única de modal ou diálogo

🧠 Exemplo de Código Prático (com UI)

Clicar no botão Enviar inicia o processo de envio. Não importa quantas vezes você clique durante a transmissão, será ignorado e a próxima transmissão não será aceita até que o primeiro processo seja concluído.

ts
import { fromEvent } from 'rxjs';
import { exhaustMap, delay } from 'rxjs';
import { ajax } from 'rxjs/ajax';

// Criar botão
const submitButton = document.createElement('button');
submitButton.textContent = 'Enviar';
document.body.appendChild(submitButton);

// Criar área de saída
const output = document.createElement('div');
output.style.marginTop = '10px';
document.body.appendChild(output);

// Processamento de envio
fromEvent(submitButton, 'click')
  .pipe(
    exhaustMap(() => {
      output.textContent = 'Enviando...';
      return ajax
        .post('https://jsonplaceholder.typicode.com/posts', {
          title: 'foo',
          body: 'bar',
          userId: 1,
        })
        .pipe(delay(2000)); // Simula atraso de envio de 2 segundos
    })
  )
  .subscribe({
    next: (response) => {
      output.textContent = 'Envio bem-sucedido!';
      console.log('Envio bem-sucedido:', response);
    },
    error: (error) => {
      output.textContent = 'Erro de envio';
      console.error('Erro de envio:', error);
    },
  });
  • Quaisquer outros cliques enquanto o botão estiver sendo clicado serão ignorados.
  • Após 2 segundos, você verá "Envio bem-sucedido!" ou "Erro de envio" será exibido.

Lançado sob a licença CC-BY-4.0.