Microtasks vs Macrotasks
O Node.js agenda trabalho assíncrono em duas famílias de filas - microtasks (Promises, queueMicrotask, process.nextTick) e macrotasks (timers, setImmediate) - e a ordem de esgotamento explica bugs sutis de timing.
Busque em todas as páginas da documentação
O Node.js agenda trabalho assíncrono em duas famílias de filas - microtasks (Promises, queueMicrotask, process.nextTick) e macrotasks (timers, setImmediate) - e a ordem de esgotamento explica bugs sutis de timing.
Tabela de referência de ordenação (simplificada):
1. Executa a call stack até ficar vazia
2. Esgota TODAS as callbacks de process.nextTick
3. Esgota TODAS as microtasks (Promises, queueMicrotask)
4. Executa UMA macrotask (timer, I/O, setImmediate, ...)
5. Repete a partir do passo 2
process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('promise'));
setTimeout(() => console.log('timer'), 0);
// nextTick → promise → timerQuando usar isso:
awaitnextTick, queueMicrotask e setImmediateimport { setTimeout, setImmediate } from 'node:timers';
async function chain(): Promise<void> {
console.log('A');
await Promise.resolve();
console.log('B');
}
chain();
Promise.resolve().then(() => console.log('C'));
process.nextTick(() => console.log('D'));
setTimeout(() => console.log('E'), 0);
console.log('F');
// A, F, D, C, B, E (B pode intercalar com C dependendo do timing do await)// Perigoso: nextTick recursivo causa starvation de I/O
function spin(count: number): void {
if (count <= 0) return;
process.nextTick(() => spin(count - 1));
}
// spin(1_000_000); // Nunca faça isso em produçãoO que isso demonstra:
A, F) é executado antes de qualquer trabalho assíncrono enfileiradonextTick precede as microtasks de Promiseawait divide funções assíncronas em continuações de microtasknextTick recursivo impede que macrotasks (incluindo I/O) sejam executadassetImmediate, etc.process.nextTick é tecnicamente separado da fila de microtasks de Promise, mas é executado antes dela.queueMicrotask agenda microtasks compatíveis com o padrão - prefira-o em vez de nextTick para adiamento genérico.| API | Tipo de Fila | Executa antes |
|---|---|---|
process.nextTick | nextTick | Promises, timers |
Promise.then / await | microtask | Próxima macrotask |
queueMicrotask | microtask | Próxima macrotask |
setTimeout / setInterval | macrotask (timers) | Próximo tick do loop |
setImmediate | macrotask (check) | Próxima iteração após poll |
// Adia de forma segura - não preempte a fila de Promises como nextTick
function defer(fn: () => void): void {
queueMicrotask(fn);
}
// Executa após o lote de I/O atual, não antes de outras microtasks
import { setImmediate } from 'node:timers';
function deferMacrotask(fn: () => void): void {
setImmediate(fn);
}process.nextTick recursivo - causa starvation de timers e I/O indefinidamente. Correção: use setImmediate para lotes ou um worker.await torna o código "paralelo" - ele apenas cede microtasks na mesma thread. Correção: use workers para paralelismo de CPU.nextTick com cadeias de Promises para hacks de ordenação - frágil entre versões do Node. Correção: reestruture com máquinas de estado explícitas ou filas.try/catch em torno de await em manipuladores de eventos.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
queueMicrotask | Adia compatível com o padrão após a pilha atual | Você precisa de timing da fase de verificação (setImmediate) |
setImmediate | Agrupa trabalho após o poll de I/O | Você precisa de ordenação de Promise antes da próxima macrotask |
| Fila de jobs (BullMQ) | Trabalho assíncrono entre processos | Experimentos de ordenação em processo |
Bibliotecas de mutex async | Serializa o acesso a estado compartilhado | Adiação simples de uso único |
Microtasks. .then, .catch, .finally e continuações de await usam a fila de microtasks.
API histórica que antecede as microtasks no Node. nextTick é executado antes das Promises - às vezes usado em internos de streams; evite em código de aplicativo.
Todas elas - a fila é completamente esgotada antes que a próxima macrotask comece.
Depois - setImmediate é uma macrotask. Todas as microtasks pendentes são esgotadas primeiro.
Uma função async sempre retorna uma Promise. O código após await é agendado como microtasks.
Cadeias infinitas de microtasks podem esgotar a memória ou causar starvation de I/O - risco semelhante ao nextTick recursivo.
Navegadores não possuem process.nextTick e setImmediate. As regras de ordenação de setTimeout(0) vs Promise são semelhantes.
Sim - ele agenda na fila de microtasks para a iteração atual do loop, após a limpeza da call stack atual.
Escreva testes de ordenação explícitos com node:test e arrays de log - mas prefira eliminar dependências de ordem no código do aplicativo.
Continuações de microtask após a resolução da Promise, e depois mais macrotasks para I/O de socket por baixo.
Não - essa é uma API do navegador. As microtasks do Node vêm de Promises e queueMicrotask.
Raramente - internos legados de streams o usavam por compatibilidade. O código de aplicativo deve usar queueMicrotask ou setImmediate.
Versões da Stack: Esta página foi escrita para Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, e NestJS 11.
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026