Fácil JavaScript

Ordem de execução com setTimeout e Promise

Enunciado

Escreva um programa que imprima na ordem correta: primeiro A (síncrono), depois B (microtarefa) e por último C (macrotarefa). Use console.log, Promise.resolve().then e setTimeout.

Requisitos

  • Imprimir 'A' de forma síncrona
  • Agendar 'B' como microtarefa usando Promise
  • Agendar 'C' como macrotarefa usando setTimeout com delay 0
  • A saída deve ser exatamente: A, B, C (cada um em uma linha)

Código inicial

// Complete o código para imprimir A, B, C na ordem correta
console.log('A');

// Agende B como microtarefa

// Agende C como macrotarefa

Saída esperada

A
B
C
Ver dica

Microtarefas são executadas antes de macrotarefas. Use Promise.resolve().then() para microtarefa e setTimeout(fn, 0) para macrotarefa.

Mostrar solução
// Imprime 'A' imediatamente (síncrono)
console.log('A');

// Agenda 'B' como microtarefa usando Promise
Promise.resolve().then(() => {
  console.log('B');
});

// Agenda 'C' como macrotarefa usando setTimeout
setTimeout(() => {
  console.log('C');
}, 0);

Passo a passo

  1. console.log('A') é executado na call stack imediatamente, imprimindo 'A'.
  2. Promise.resolve().then(...) agenda o callback para a fila de microtarefas.
  3. setTimeout(..., 0) agenda o callback para a fila de tarefas (macrotarefas).
  4. A call stack fica vazia após o último console.log síncrono.
  5. O event loop verifica a fila de microtarefas primeiro e executa o callback da Promise, imprimindo 'B'.
  6. Depois de esvaziar as microtarefas, o event loop pega a macrotarefa e executa o callback do setTimeout, imprimindo 'C'.

Por que funciona

O event loop prioriza microtarefas sobre macrotarefas. Mesmo que o setTimeout tenha delay 0, ele só será executado após todas as microtarefas pendentes. Isso garante que 'B' (microtarefa) saia antes de 'C' (macrotarefa).

Erros comuns

  • Achar que setTimeout(fn, 0) executa imediatamente: Ele vai para a fila de tarefas e só roda depois das microtarefas.
  • Usar setTimeout sem delay: setTimeout(fn) tem delay 0 por padrão, mas ainda é macrotarefa.
  • Esquecer de retornar a Promise: Não é necessário aqui, mas em outros casos pode causar erros.

Outra forma de resolver

Usar queueMicrotask para agendar a microtarefa:

console.log('A');
queueMicrotask(() => console.log('B'));
setTimeout(() => console.log('C'), 0);

queueMicrotask é mais explícito para microtarefas, mas Promise.resolve().then é mais comum.

Saída esperada

A
B
C