Filas de Tarefas em TypeScript: Guia Prático

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Trabalhando com Filas de Tarefas em TypeScript: na prática

\n

Em aplicações web modernas, surge frequentemente a necessidade de executar operações longas ou que consomem muitos recursos de forma assíncrona, sem bloquear o fluxo principal do usuário. Envio de campanhas de e-mail, geração de relatórios em PDF, processamento de imagens carregadas — todos esses são candidatos ideais para serem transferidos para tarefas em segundo plano. Uma fila de tarefas (task queue) é um padrão arquitetural comprovado que permite organizar a execução confiável de tais operações. Neste artigo, vamos analisar como criar e usar filas de tarefas em TypeScript na prática, utilizando bibliotecas e abordagens populares.

\n

Abordaremos a criação de uma fila simples, o trabalho com prioridades, o tratamento de erros e a integração com Redis através da biblioteca BullMQ. Todos os exemplos serão escritos em TypeScript com ênfase em tipagem estrita.

\n\n

1. Fundamentos: criando uma fila de tarefas simples

\n

Para começar, vamos implementar uma fila de tarefas simples sem dependências externas. Isso ajudará a entender os princípios básicos de funcionamento. Nossa fila armazenará funções-tarefa e as executará sequencialmente.

\n
type Task<T> = () => Promise<T>;\n\ninterface TaskItem<T> {\n  task: Task<T>;\n  resolve: (value: T | PromiseLike<T>) => void;\n  reject: (reason?: any) => void;\n}\n\nclass SimpleQueue {\n  private queue: TaskItem<any>[] = [];\n  private isProcessing = false;\n\n  add<T>(task: Task<T>): Promise<T> {\n    return new Promise<T>((resolve, reject) => {\n      this.queue.push({ task, resolve, reject });\n      this.process();\n    });\n  }\n\n  private async process(): Promise<void> {\n    if (this.isProcessing || this.queue.length === 0) return;\n    this.isProcessing = true;\n\n    const item = this.queue.shift()!;\n    try {\n      const result = await item.task();\n      item.resolve(result);\n    } catch (error) {\n      item.reject(error);\n    } finally {\n      this.isProcessing = false;\n      this.process();\n    }\n  }\n}\n\n// Uso\nconst queue = new SimpleQueue();\n\nqueue.add(async () => {\n  console.log('Tarefa 1 iniciada');\n  await new Promise(r => setTimeout(r, 1000));\n  console.log('Tarefa 1 concluída');\n  return 'Resultado 1';\n});\n\nqueue.add(async () => {\n  console.log('Tarefa 2 iniciada');\n  return 'Resultado 2';\n});
\n

Este exemplo demonstra a mecânica básica: as tarefas são adicionadas a um array e executadas em ordem. Cada tarefa retorna uma Promise, o que permite trabalhar convenientemente com os resultados. No entanto, essa abordagem tem limitações: não há suporte para prioridades, novas tentativas e preservação de estado ao reiniciar a aplicação.

\n\n

2. Priorização e tratamento de erros

\n

Em projetos reais, as tarefas geralmente têm diferentes níveis de importância. Por exemplo, a tarefa de envio de um e-mail transacional deve ser executada antes da tarefa de limpeza de arquivos temporários. Vamos adicionar prioridades à nossa fila.

\n
type Priority = 'high' | 'medium' | 'low';\n\ninterface PriorityTask<T> {\n  task: Task<T>;\n  priority: Priority;\n  resolve: (value: T) => void;\n  reject: (reason?: any) => void;\n  retries: number;\n}\n\nclass PriorityQueue {\n  private high: PriorityTask<any>[] = [];\n  private medium: PriorityTask<any>[] = [];\n  private low: PriorityTask<any>[] = [];\n  private isProcessing = false;\n  private maxRetries = 3;\n\n  add<T>(task: Task<T>, priority: Priority = 'medium'): Promise<T> {\n    return new Promise<T>((resolve, reject) => {\n      const taskItem: PriorityTask<T> = {\n        task,\n        priority,\n        resolve,\n        reject,\n        retries: 0\n      };\n      this.getQueue(priority).push(taskItem);\n      this.process();\n    });\n  }\n\n  private getQueue(priority: Priority): PriorityTask<any>[] {\n    switch (priority) {\n      case 'high': return this.high;\n      case 'medium': return this.medium;\n                

Blogs

Book Recommendations