Skip to content

Event Loop de Node.js

Si vous vous aventurez dans le monde de Node.js ou si vous explorez simplement le fonctionnement interne des systèmes asynchrones, vous avez probablement entendu parler de l'Event Loop (ou "boucle d'événements" en français). Dans ce tutoriel, nous allons décomposer ce concept avec des exemples concrets de la vie de tous les jours pour faciliter la compréhension.

Qu'est-ce que l'Event Loop?

L'Event Loop, c'est comme un maître d'hôtel dans un restaurant

Imaginez que vous soyez dans un restaurant. Dans ce restaurant, il y a un seul maître d'hôtel (représentant notre Event Loop) et plusieurs cuisiniers en cuisine.

  1. Les clients et les commandes:

    • Les clients qui arrivent au restaurant sont comme des "tâches" ou des "requêtes" dans notre programme. Chaque client a une commande spécifique (une opération à effectuer).
  2. Le rôle du maître d'hôtel:

    • Le maître d'hôtel prend la commande du client et la donne à la cuisine. Si la commande est rapide (par exemple, servir un verre d'eau), il le fait immédiatement. Si la commande nécessite du temps (par exemple, cuisiner un plat), il la confie à la cuisine et continue de prendre d'autres commandes.
    • Il ne reste pas inactif en attendant qu'une tâche soit terminée. Il continue de prendre d'autres commandes, exactement comme l'Event Loop qui continue de traiter d'autres tâches sans attendre qu'une opération asynchrone soit terminée.
  3. Les cuisiniers et les tâches asynchrones:

    • Une fois la commande prête, le cuisinier informe le maître d'hôtel (comme une "callback" ou une "promesse" qui est résolue dans le monde de la programmation). Le maître d'hôtel sert alors le plat au client approprié.
    • Cela représente le moment où, dans notre programme, une tâche asynchrone (comme une requête à une base de données) est terminée et le résultat est prêt à être traité.
  4. L'efficacité du maître d'hôtel:

    • Si le maître d'hôtel attendait chaque commande pour être préparée avant de prendre une nouvelle commande, les clients attendraient très longtemps. Grâce à son mode de fonctionnement, il peut gérer plusieurs commandes en même temps, optimisant ainsi l'efficacité du service.

Fonctionnement de l'Event Loop

Event Loop

Le fonctionnement de l'Event Loop est l'un des aspects fondamentaux pour comprendre l'asynchronicité en JavaScript, en particulier dans des environnements comme Node.js. Voici comment l'Event Loop fonctionne, étape par étape:

  1. Initialisation: Lorsque vous exécutez un script JavaScript, l'Event Loop démarre, et le script est traité comme une tâche initiale.

  2. Call Stack (Pile d'appels): JavaScript possède une pile d'appels où il empile les fonctions à exécuter. Lorsqu'une fonction est appelée, elle est ajoutée à la pile. Lorsqu'elle a terminé son exécution, elle est retirée de la pile. C'est une structure "LIFO" (Last In, First Out).

LIFO ?

LIFO signifie "Last In, First Out" (Dernier entré, premier sorti). C'est une méthode de gestion des éléments où le dernier élément ajouté est le premier à être retiré. Une pile (ou "stack" en anglais) est l'exemple classique d'une structure de données LIFO.

Imaginez une pile d'assiettes. Lorsque vous ajoutez une assiette à la pile, elle se place au-dessus. Lorsque vous voulez retirer une assiette, vous prenez toujours celle du dessus. Vous n'accédez jamais directement à une assiette au milieu ou au bas de la pile sans d'abord retirer celles qui sont au-dessus.

  1. Node APIs: Lorsqu'il y a des fonctions asynchrones (comme setTimeout, setInterval, ou des opérations I/O), elles sont envoyées hors de cette pile pour être traitées. Par exemple, setTimeout sera géré par les timers dans Node.js.

  2. Callback Queue (File d'attente des callbacks): Une fois que ces fonctions asynchrones sont terminées, leurs callbacks (si présents) sont envoyés dans une file d'attente. Par exemple, après l'expiration d'un setTimeout, son callback sera placé ici.

  3. Retour à la pile d'appels: Si et seulement si la pile d'appels est vide, l'Event Loop prendra le premier élément de la file d'attente des callbacks et le poussera dans la pile d'appels pour son exécution. Ce processus se poursuit jusqu'à ce que la file d'attente des callbacks soit vide.

  4. Loop: Ce processus est répété continuellement, d'où le nom "boucle d'événements" ou "Event Loop". L'Event Loop vérifie continuellement la pile d'appels pour voir si elle est vide, et si elle l'est, elle prend des callbacks de la file d'attente pour les exécuter.


Exemple simplifié:

javascript
console.log("Début");

setTimeout(() => {
    console.log("Timeout");
}, 2000);

console.log("Fin");
console.log("Début");

setTimeout(() => {
    console.log("Timeout");
}, 2000);

console.log("Fin");

Dans cet exemple:

  1. Le message "Début" est affiché immédiatement.
  2. setTimeout est appelé, mais sa callback est déléguée à Node APIs pour attendre. L'exécution du script continue sans attendre ces 2 secondes.
  3. Le message "Fin" est affiché.
  4. Après 2 secondes, la callback de setTimeout est placée dans la file d'attente des callbacks.
  5. La pile d'appels étant vide à ce moment-là, l'Event Loop prend la callback de setTimeout et la pousse dans la pile d'appels pour exécution.
  6. Le message "Timeout" est affiché.

C'est ainsi que JavaScript parvient à être non bloquant et asynchrone, malgré le fait qu'il soit mono-threadé.