Comprendre la Boucle d’Événements (Event Loop) de Node.js : Un Guide Détaillé
Si vous travaillez avec Node.js, vous avez probablement entendu parler de la boucle d’événements (event loop). Mais savez-vous vraiment comment elle fonctionne ? Dans cet article, je vais vous expliquer en détail les différentes phases de la boucle d’événements et ce que signifie « chaque phase a une file d’attente (queue) ».
1. Les Phases de la Boucle d’Événements
La boucle d’événements est divisée en plusieurs phases, chacune ayant une file d’attente (queue) spécifique pour les tâches à exécuter. Voici les phases principales, dans l’ordre dans lequel elles sont traitées :
1.1 Timers
- Rôle : Exécute les callbacks des fonctions
setTimeout()
etsetInterval()
. - Exemple : Si vous avez un
setTimeout(() => {}, 1000)
, le callback sera exécuté dans cette phase après 1 seconde.
1.2 Pending Callbacks (I/O Callbacks)
- Rôle : Exécute les callbacks des opérations d’entrée/sortie (I/O) qui ont été terminées, comme les erreurs de connexion réseau ou les lectures de fichiers.
- Exemple : Si vous lisez un fichier avec
fs.readFile()
, le callback sera exécuté ici une fois la lecture terminée.
1.3 Idle, Prepare
- Rôle : Phases internes utilisées par Node.js pour préparer la boucle d’événements. En tant que développeur, vous n’interagissez pas directement avec ces phases.
1.4 Poll
- Rôle : C’est la phase principale où Node.js attend de nouveaux événements I/O (comme des données réseau ou des fichiers). Elle gère également les callbacks des opérations I/O terminées.
- Exemple : Si vous attendez une réponse d’un serveur, Node.js reste dans cette phase jusqu’à ce que la réponse arrive.
- Comportement :
- Si la file d’attente de la phase Poll est vide, Node.js vérifie s’il y a des
setImmediate()
à exécuter. Si oui, il passe à la phase Check. - Si aucun
setImmediate()
n’est en attente, Node.js attend de nouveaux événements I/O.
- Si la file d’attente de la phase Poll est vide, Node.js vérifie s’il y a des
1.5 Check
- Rôle : Exécute les callbacks de
setImmediate()
. - Exemple : Si vous avez un
setImmediate(() => {})
, le callback sera exécuté dans cette phase.
1.6 Close Callbacks
- Rôle : Exécute les callbacks liés à la fermeture d’événements, comme la fermeture d’une connexion réseau ou d’un fichier.
- Exemple : Si vous fermez un serveur avec
server.close()
, le callback sera exécuté ici.
2. Que Signifie « Chaque Phase a une File d’Attente (Queue) » ?
Chaque phase de la boucle d’événements a une file d’attente (queue) qui contient les tâches à exécuter. Voici comment cela fonctionne :
- File d’attente (queue) : Une structure de données qui stocke les tâches dans l’ordre où elles ont été ajoutées (premier entré, premier sorti, ou FIFO pour « First In, First Out »).
- Exécution des tâches : Dans chaque phase, Node.js prend les tâches de la file d’attente une par une et les exécute jusqu’à ce que la file soit vide ou qu’une limite de temps soit atteinte.
Exemple Concret :
Imaginons que vous avez le code suivant :
setTimeout(() => {
console.log('setTimeout');
}, 0);
setImmediate(() => {
console.log('setImmediate');
});
fs.readFile('file.txt', () => {
console.log('File read');
});
Voici comment la boucle d’événements traite ce code :
- Phase Timers :
- La file d’attente contient le callback de
setTimeout
. - Node.js exécute
console.log('setTimeout')
.
- La file d’attente contient le callback de
- Phase Pending Callbacks :
- Si une opération I/O (comme la lecture du fichier) est terminée, son callback est ajouté ici.
- Node.js exécute
console.log('File read')
.
- Phase Poll :
- Node.js attend de nouveaux événements I/O. Si rien n’est en attente, il passe à la phase suivante.
- Phase Check :
- La file d’attente contient le callback de
setImmediate
. - Node.js exécute
console.log('setImmediate')
.
- La file d’attente contient le callback de
- Phase Close Callbacks :
- Si des événements de fermeture sont en attente, leurs callbacks sont exécutés ici.
3. Ordre des Phases
Voici l’ordre dans lequel les phases sont traitées dans la boucle d’événements :
- Timers → 2. Pending Callbacks → 3. Idle, Prepare → 4. Poll → 5. Check → 6. Close Callbacks
Une fois que toutes les phases sont traitées, la boucle recommence depuis le début (Timers).
4. Pourquoi Cette Organisation ?
Cette organisation permet à Node.js de gérer efficacement les opérations asynchrones tout en restant non bloquant. Chaque phase a un rôle spécifique, et les tâches sont exécutées dans un ordre prévisible.
5. Résumé des Phases et de Leurs Files d’Attente
Phase | Rôle | Exemple de Tâches |
---|---|---|
Timers | Exécute les callbacks de setTimeout() et setInterval() . |
setTimeout(() => {}, 1000) |
Pending Callbacks | Exécute les callbacks des opérations I/O terminées. | Callback de fs.readFile() |
Idle, Prepare | Phases internes pour préparer la boucle d’événements. | Non utilisé directement par les développeurs. |
Poll | Attend de nouveaux événements I/O et exécute leurs callbacks. | Attendre une réponse réseau. |
Check | Exécute les callbacks de setImmediate() . |
setImmediate(() => {}) |
Close Callbacks | Exécute les callbacks liés à la fermeture d’événements. | server.close(() => {}) |
6. En Résumé
- La boucle d’événements est divisée en phases, chacune ayant une file d’attente pour les tâches à exécuter.
- Les phases sont traitées dans un ordre spécifique, et chaque phase a un rôle précis (Timers, I/O, Poll, Check, etc.).
- Cette organisation permet à Node.js de gérer les opérations asynchrones de manière efficace et non bloquante.