Entendendo setImmediate()
Quando você quer executar algum trecho de código assincronamente, mas o mais rápido possível, uma opção é usar a função setImmediate()
fornecida pelo Node.js:
setImmediate(() => {
// faça algo
})
Qualquer função passada como argumento para setImmediate()
é um callback que é executado na próxima iteração do loop de eventos.
Qual a diferença entre setImmediate()
e setTimeout(() => {}, 0)
(passando um timeout de 0ms), e entre 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 de 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. Um callback Promise.then()
é adicionado à fila de microtarefas promises. Um callback setTimeout
, setImmediate
é adicionado à fila de macrotarefas.
O loop de eventos executa as tarefas na fila process.nextTick primeiro, e então executa a fila de microtarefas promises, e então executa a fila de macrotarefas setTimeout
ou setImmediate
.
Aqui está um exemplo para mostrar a ordem entre setImmediate()
, process.nextTick()
e Promise.then()
:
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()
, então chamará foo()
na fila process.nextTick. Depois disso, ele lidará com a fila de microtarefas promises, que imprime bar e adiciona zoo()
na fila process.nextTick ao mesmo tempo. Então ele chamará zoo()
que acabou de ser adicionado. No final, o baz()
na fila de macrotarefas é chamado.
O princípio mencionado acima é verdadeiro em casos CommonJS, mas tenha em mente que em Módulos ES, por exemplo, arquivos mjs
, a ordem de execução será diferente:
// start bar foo zoo baz
Isso ocorre porque o Módulo ES sendo carregado é encapsulado como uma operação assíncrona e, portanto, todo o script já está na fila de microtarefas promises. Portanto, quando a promessa é resolvida imediatamente, seu callback é anexado à fila de microtarefas. O Node.js tentará limpar a fila até passar para qualquer outra fila e, portanto, você verá que ele produz bar primeiro.