Node.js - Boucle d'événements : Dévoiler la magie derrière le JavaScript asynchrone

Bonjour à tous, futurs magiciens de la programmation ! Aujourd'hui, nous allons entreprendre un voyage passionnant au cœur de Node.js - la Boucle d'événements. Ne vous inquiétez pas si vous n'avez jamais écrit une ligne de code auparavant ; je serai votre guide amical à travers ce monde fascinant. À la fin de ce tutoriel, vous comprendrez comment Node.js parvient à faire tellement de choses à la fois, tout comme vous jonglez avec les devoirs, Netflix et les messages à vos amis !

Node.js - Event Loop

Qu'est-ce que la Boucle d'événements ?

Imaginez que vous êtes un cuisinier dans une cuisine de restaurant très occupée. Vous avez plusieurs plats en cuisson, des minuteurs qui tic-tac et des commandes qui arrivent. Comment gérez-vous tout cela sans brûler la nourriture ou faire attendre les clients ? C'est essentiellement ce que la Boucle d'événements fait pour Node.js !

La Boucle d'événements est comme un chef principal, vérifiant constamment ce qui nécessite de l'attention et s'assurant que tout se passe en douceur. C'est la sauce secrète qui permet à Node.js de réaliser des opérations I/O non bloquantes, bien que JavaScript soit单线程的.

Concepts Clés

Avant de plonger plus profondément, familiarisons-nous avec quelques concepts clés :

  1. 单线程 : JavaScript s'exécute sur un seul thread, ce qui signifie qu'il ne peut faire qu'une chose à la fois.
  2. Non-bloquant : Node.js peut gérer plusieurs opérations sans attendre que chacune se termine avant de passer à la suivante.
  3. Asynchrone : Les tâches peuvent être démarrées maintenant et terminées plus tard, permettant à d'autres codes de s'exécuter entre-temps.

Comment fonctionne la Boucle d'événements ?

Décomposons la Boucle d'événements en étapes digestes :

  1. Exécuter le code synchrone dans la pile d'appels
  2. Vérifier les timers (setTimeout, setInterval)
  3. Vérifier les opérations I/O en attente
  4. Exécuter les callbacks setImmediate
  5. Gérer les événements 'close'

Voyons cela en action avec quelques exemples de code !

Exemple 1 : Code Synchrone vs. Asynchrone

console.log("Premier");

setTimeout(() => {
console.log("Deuxième");
}, 0);

console.log("Troisième");

Que pensez-vous de la sortie ? Décomposons cela :

  1. "Premier" est enregistré immédiatement.
  2. setTimeout est rencontré, mais au lieu d'attendre, Node.js met un timer et continue.
  3. "Troisième" est enregistré.
  4. La Boucle d'événements vérifie les timers terminés et exécute le callback, enregistrant "Deuxième".

Sortie :

Premier
Troisième
Deuxième

Surpris ? Cela montre comment Node.js gère les opérations asynchrones sans bloquer le thread principal.

Exemple 2 : Multiples Timers

setTimeout(() => console.log("Timer 1"), 0);
setTimeout(() => console.log("Timer 2"), 0);
setTimeout(() => console.log("Timer 3"), 0);

console.log("Bonjour depuis le thread principal !");

Dans cet exemple, nous définissons plusieurs timers avec un délai de 0 millisecondes. Cependant, la Boucle d'événements les traitera toujours après que le thread principal a terminé.

Sortie :

Bonjour depuis le thread principal !
Timer 1
Timer 2
Timer 3

Les Phases de la Boucle d'événements

Maintenant que nous avons vu la Boucle d'événements en action, explorons ses phases en détail :

1. Phase des Timers

Cette phase exécute les callbacks planifiés par setTimeout() et setInterval().

setTimeout(() => console.log("Je suis un timer !"), 100);
setInterval(() => console.log("Je répète toutes les secondes"), 1000);

2. Phase des Callbacks en Attente

Ici, la boucle exécute les callbacks I/O reportés à l'itération suivante de la boucle.

3. Phase d'Idle, de Préparation

Usage interne uniquement. Rien à voir ici, les amis !

4. Phase de Poll

Récupère les nouveaux événements I/O et exécute les callbacks liés aux I/O.

const fs = require('fs');

fs.readFile('example.txt', (err, data) => {
if (err) throw err;
console.log(data);
});

5. Phase de Check

Les callbacks setImmediate() sont invoqués ici.

setImmediate(() => console.log("Je suis immédiat !"));

6. Phase des Callbacks de Close

Certains callbacks de close, par exemple, socket.on('close', ...), sont traités ici.

Mettre tout ensemble

Créons un exemple plus complexe qui utilise différents aspects de la Boucle d'événements :

const fs = require('fs');

console.log("Début");

setTimeout(() => console.log("Timeout 1"), 0);
setImmediate(() => console.log("Immediate 1"));

fs.readFile('example.txt', (err, data) => {
console.log("Lecture du fichier terminée");
setTimeout(() => console.log("Timeout 2"), 0);
setImmediate(() => console.log("Immediate 2"));
});

console.log("Fin");

L'ordre d'exécution pourrait vous surprendre :

  1. "Début" et "Fin" sont enregistrés immédiatement.
  2. Le premier setTimeout et setImmediate sont mis en file.
  3. L'opération de lecture de fichier commence.
  4. La Boucle d'événements commence ses cycles :
  • Le premier callback de setTimeout s'exécute.
  • Le premier callback de setImmediate s'exécute.
  • Lorsque la lecture du fichier est terminée, son callback est exécuté.
  • À l'intérieur du callback de lecture du fichier, un autre setTimeout et setImmediate sont mis en file.
  • Le deuxième setImmediate s'exécute avant le deuxième setTimeout.

Méthodes Communes de la Boucle d'événements

Voici un tableau des méthodes courantes liées à la Boucle d'événements dans Node.js :

Méthode Description
setTimeout(callback, delay) Exécute le callback après un délai en millisecondes
setInterval(callback, interval) Exécute le callback à intervalle régulier
setImmediate(callback) Exécute le callback à la prochaine itération de la Boucle d'événements
process.nextTick(callback) Ajoute le callback à la "file de next tick" qui est traitée après l'opération actuelle

Conclusion

Félicitations ! Vous avez刚刚迈出了进入Node.js和其Boucle d'événements fascinante monde. Souvenez-vous, comme apprendre à rouler à vélo, maîtriser la programmation asynchrone nécessite de la pratique. Ne soyez pas découragé si cela ne vous vient pas tout de suite - continuez à expérimenter et bientôt vous écrirez du code non-bloquant comme un pro !

Pour conclure, voici une analogie amusante : pensez à la Boucle d'événements comme un carrousel. Les différentes tâches (comme les timers, les opérations I/O et les callbacks immédiats) sont comme des enfants essayant de monter. La Boucle d'événements continue de tourner, prenant et déposant des tâches dans un ordre spécifique, assurant que chacun a un tour sans arrêter le carrousel.

Continuez à coder, restez curieux, et souvenez-vous - dans le monde de Node.js, la patience n'est pas seulement une vertu, c'est un callback !

Credits: Image by storyset