La boucle d'événements de Node.js semble mystérieuse jusqu'à ce que vous cessiez de la considérer comme une seule file d'attente.
Il y a plusieurs files d'attente et plusieurs priorités impliquées, et la partie la plus déroutante pour de nombreux ingénieurs est que les micro-tâches ne sont pas la même chose que la boucle de phases principale de libuv.
Un Modèle Mental Utile
Ce script est un bon point de départ :
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
Promise.resolve().then(() => console.log("promise"));
process.nextTick(() => console.log("nextTick"));
console.log("sync");
Les concepts importants sont :
- le code synchrone s'exécute en premier
process.nextTick s'exécute avant d'autres micro-tâches dans Node
- les rappels de promesse s'exécutent avant que la boucle d'événements ne passe aux phases ultérieures
- les temporisateurs et
setImmediate appartiennent à différentes phases ultérieures
C'est pourquoi process.nextTick est si puissant et si facile à mal utiliser.
Pourquoi nextTick Peut Vous Nuire
Si vous planifiez récursivement davantage de travail avec nextTick, vous pouvez affamer l'I/O car Node continue de vider cette file d'attente avant de passer à autre chose.
C'est pourquoi nextTick doit être utilisé avec parcimonie.
Si vous devez céder afin que la boucle d'événements puisse continuer à servir le processus, setImmediate est souvent l'outil le plus sain.
La Valeur Technique
Ce n'est pas une simple question de trivia d'entretien.
Cela compte lorsque vous êtes :
- en train de diagnostiquer des pics de latence
- en train de déboguer un ordre de rappel étrange
- essayant d'éviter d'affamer l'I/O
La boucle d'événements cesse de sembler magique une fois que vous pensez en termes de files d'attente et de points de planification au lieu de "le code asynchrone se produit plus tard."
Lectures Complémentaires