Comprendere setImmediate()
Quando si desidera eseguire un frammento di codice in modo asincrono, ma il più presto possibile, un'opzione è utilizzare la funzione setImmediate()
fornita da Node.js:
setImmediate(() => {
// fai qualcosa
})
Qualsiasi funzione passata come argomento a setImmediate()
è una callback che viene eseguita nella successiva iterazione del loop degli eventi.
In che modo setImmediate()
si differenzia da setTimeout(() => {}, 0)
(passando un timeout di 0 ms), e da process.nextTick()
e Promise.then()
?
Una funzione passata a process.nextTick()
verrà eseguita nell'iterazione corrente del loop degli eventi, dopo la fine dell'operazione corrente. Ciò significa che verrà sempre eseguita prima di setTimeout
e setImmediate
.
Una callback setTimeout()
con un ritardo di 0 ms è molto simile a setImmediate()
. L'ordine di esecuzione dipenderà da vari fattori, ma entrambi verranno eseguiti nella successiva iterazione del loop degli eventi.
Una callback process.nextTick
viene aggiunta alla coda process.nextTick. Una callback Promise.then()
viene aggiunta alla coda microtask delle promise. Una callback setTimeout
, setImmediate
viene aggiunta alla coda macrotask.
Il loop degli eventi esegue prima le attività nella coda process.nextTick, poi esegue la coda microtask delle promise, e poi esegue la coda macrotask setTimeout
o setImmediate
.
Ecco un esempio per mostrare l'ordine tra 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
Questo codice chiamerà prima start()
, poi chiamerà foo()
nella coda process.nextTick. Dopodiché, gestirà la coda microtask delle promise, che stampa bar e aggiunge zoo()
nella coda process.nextTick contemporaneamente. Quindi chiamerà zoo()
che è appena stato aggiunto. Alla fine, viene chiamata baz()
nella coda macrotask.
Il principio sopra menzionato vale nei casi CommonJS, ma tenere presente che nei moduli ES, ad esempio i file mjs
, l'ordine di esecuzione sarà diverso:
// start bar foo zoo baz
Questo perché il modulo ES caricato è racchiuso come un'operazione asincrona e quindi l'intero script è in realtà già nella coda microtask delle promise. Quindi, quando la promise viene risolta immediatamente, la sua callback viene aggiunta alla coda microtask. Node.js tenterà di svuotare la coda prima di passare a qualsiasi altra coda, e quindi vedrete che stampa prima bar.