Comprendre setImmediate()
Lorsque vous souhaitez exécuter un morceau de code de manière asynchrone, mais le plus tôt possible, une option consiste à utiliser la fonction setImmediate()
fournie par Node.js :
setImmediate(() => {
// faire quelque chose
})
Toute fonction passée en argument à setImmediate()
est une fonction de rappel qui est exécutée lors de la prochaine itération de la boucle d'événements.
En quoi setImmediate()
diffère-t-il de setTimeout(() => {}, 0)
(en passant un délai de 0 ms), et de process.nextTick()
et Promise.then()
?
Une fonction passée à process.nextTick()
sera exécutée lors de l'itération actuelle de la boucle d'événements, une fois l'opération courante terminée. Cela signifie qu'elle sera toujours exécutée avant setTimeout
et setImmediate
.
Une fonction de rappel setTimeout()
avec un délai de 0 ms est très similaire à setImmediate()
. L'ordre d'exécution dépendra de divers facteurs, mais les deux seront exécutés lors de la prochaine itération de la boucle d'événements.
Une fonction de rappel process.nextTick
est ajoutée à la file d'attente process.nextTick. Une fonction de rappel Promise.then()
est ajoutée à la file d'attente des microtâches des promesses. Une fonction de rappel setTimeout
, setImmediate
est ajoutée à la file d'attente des macrotâches.
La boucle d'événements exécute d'abord les tâches de la file d'attente process.nextTick, puis exécute la file d'attente des microtâches des promesses, puis exécute la file d'attente des macrotâches setTimeout
ou setImmediate
.
Voici un exemple pour illustrer l'ordre entre setImmediate()
, process.nextTick()
et 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
Ce code appellera d'abord start()
, puis appellera foo()
dans la file d'attente process.nextTick. Ensuite, il gérera la file d'attente des microtâches des promesses, qui imprime bar et ajoute zoo()
dans la file d'attente process.nextTick en même temps. Ensuite, il appellera zoo()
qui vient d'être ajouté. Enfin, baz()
dans la file d'attente des macrotâches est appelé.
Le principe susmentionné est valable dans les cas CommonJS, mais gardez à l'esprit que dans les modules ES, par exemple les fichiers .mjs
, l'ordre d'exécution sera différent :
// start bar foo zoo baz
Ceci est dû au fait que le module ES chargé est encapsulé comme une opération asynchrone, et donc le script entier est en réalité déjà dans la file d'attente des microtâches des promesses. Ainsi, lorsque la promesse est immédiatement résolue, sa fonction de rappel est ajoutée à la file d'attente des microtâches. Node.js tentera de vider la file d'attente avant de passer à une autre file d'attente, et vous verrez donc qu'il affiche d'abord bar.