Skip to content

Entendendo setImmediate()

Quando você deseja executar algum código de forma assíncrona, mas o mais rápido possível, uma opção é usar a função setImmediate() fornecida pelo Node.js:

js
setImmediate(() => {
    // faça algo
})

Qualquer função passada como argumento setImmediate() é um callback que é executado na próxima iteração do loop de eventos.

Como setImmediate() difere de setTimeout(() => {}, 0) (passando um timeout de 0ms), e de process.nextTick() e Promise.then()?

Uma função passada para process.nextTick() será executada na iteração atual do loop de eventos, após o término da operação atual. Isso significa que sempre será executada antes de setTimeout e setImmediate.

Um callback setTimeout() com um atraso de 0ms é muito semelhante a setImmediate(). A ordem de execução dependerá de vários fatores, mas ambos serão executados na próxima iteração do loop de eventos.

Um callback process.nextTick é adicionado à fila process.nextTick queue. Um callback Promise.then() é adicionado à fila de microtarefas de promises microtask queue. Um callback setTimeout, setImmediate é adicionado à fila de macrotarefas macrotask queue.

O loop de eventos executa as tarefas na fila process.nextTick queue primeiro, e então executa a fila de microtarefas de promises promises microtask queue, e então executa a fila de macrotarefas setTimeout ou setImmediate macrotask queue.

Aqui está um exemplo para mostrar a ordem entre setImmediate(), process.nextTick() e Promise.then():

js
const baz = () => console.log('baz');
const foo = () => console.log('foo');
const zoo = () => console.log('zoo');
const start = () => {
  console.log('start');
  setImmediate(baz);
  new Promise((resolve, reject) => {
    resolve('bar');
  }).then(resolve => {
    console.log(resolve);
    process.nextTick(zoo);
  });
  process.nextTick(foo);
};
start();
// start foo bar zoo baz

Este código primeiro chamará start(), depois chamará foo() na fila process.nextTick queue. Depois disso, ele irá lidar com a fila de microtarefas de promises promises microtask queue, que imprime bar e adiciona zoo() na fila process.nextTick queue ao mesmo tempo. Então ele chamará zoo() que acabou de ser adicionado. No final, o baz() na fila de macrotarefas macrotask queue é chamado.

O princípio mencionado acima é válido em casos CommonJS, mas lembre-se que em módulos ES, por exemplo, arquivos mjs, a ordem de execução será diferente:

js
// start bar foo zoo baz

Isso ocorre porque o módulo ES sendo carregado é encapsulado como uma operação assíncrona, e assim todo o script já está na fila de microtarefas de promises promises microtask queue. Então, quando a promise é resolvida imediatamente, seu callback é anexado à fila microtask queue. O Node.js tentará limpar a fila até mover para qualquer outra fila, e portanto você verá que ele imprime bar primeiro.