Maison > Article > interface Web > Boucle d'événements dans Node.js : gestion des opérations asynchrones
Node.js est connu pour sa nature non bloquante et asynchrone, et la boucle d'événements est au cœur de ce comportement. Il garantit que le thread principal reste débloqué, permettant à plusieurs opérations de s'exécuter efficacement sans attendre la fin des autres. Dans cet article, nous explorerons le fonctionnement de la boucle d'événements, décomposerons ses six phases et discuterons des stratégies pour éviter de la bloquer.
La boucle d'événements dans Node.js permet un traitement asynchrone, évitant le blocage du thread principal. Il fonctionne en six phases :
La boucle d'événements est un mécanisme chargé de gérer les opérations asynchrones. Chaque fois qu'une opération telle qu'une E/S ou une minuterie se termine, la boucle d'événements détermine quand le rappel pour cette opération doit être exécuté. Cette conception permet à Node.js de traiter plusieurs requêtes sans bloquer le thread principal, garantissant ainsi des performances élevées dans les applications.
La boucle événementielle fonctionne de manière cyclique, passant par six phases distinctes. Chaque phase a un objectif spécifique et les rappels sont exécutés en conséquence.
1. Phase des minuteries
Cette phase exécute les rappels programmés par setTimeout et setInterval. Si le délai spécifié a expiré, le rappel associé s'exécute ici.
Exemple :
setTimeout(() => { console.log('Executed after 1 second.'); }, 1000); console.log('Timer scheduled.');
Sortie :
Timer scheduled. Executed after 1 second.
Même si le délai est de 1 000 ms, setTimeout s'exécute une fois le tick de boucle de l'événement en cours terminé.
Exemple pour setInterval
let count = 0; const intervalId = setInterval(() => { console.log(`Interval executed: ${++count}`); if (count === 3) clearInterval(intervalId); }, 500);
2. Phase de rappels en attente
Dans cette phase, la boucle d'événements traite les rappels d'E/S qui ont été différés du cycle précédent. Ces rappels gèrent les erreurs et les opérations d'E/S non bloquantes.
Exemple :
const fs = require('fs'); fs.readFile('file.txt', (err, data) => { if (err) console.error(err); else console.log(data.toString()); });
Sortie :
Read operation scheduled. File content:<contents of example.txt>
3. Idle, phase de préparation
Cette phase est utilisée en interne par Node.js pour préparer le système pour le prochain tour de sondage. Vous n'interagirez pas directement avec cette phase, mais nous pouvons simuler certains comportements qui y sont liés en nous concentrant sur des tâches telles que la configuration du sondage interne.
Exemple avec configuration du serveur TCP (état de préparation)
const net = require('net'); const server = net.createServer((socket) => { socket.end('Connection closed.'); }); server.listen(8080, () => { console.log('Server listening on port 8080.'); });
La phase de préparation initialise ce serveur. Une fois préparé, il passe à la phase d'interrogation en attente des connexions entrantes.
4. Phase de sondage
Pendant la phase poll, la boucle d'événements attend de nouveaux événements d'E/S et exécute les rappels pertinents. Si aucun événement n'est en attente, il restera dans cette phase jusqu'à ce qu'un nouvel événement se produise ou qu'un minuteur soit prêt à s'exécuter.
setTimeout(() => { console.log('Executed after 1 second.'); }, 1000); console.log('Timer scheduled.');
Ici, le serveur entre dans la phase d'interrogation en attendant les requêtes HTTP. Lorsqu'une requête arrive, son rappel est exécuté, envoyant une réponse.
5. Vérifier la phase
La phase check exécute les rappels programmés avec setImmediate. Ces rappels sont exécutés après la phase d'interrogation, qu'il y ait ou non des opérations d'E/S en attente.
Exemple :
Timer scheduled. Executed after 1 second.
Sortie :
let count = 0; const intervalId = setInterval(() => { console.log(`Interval executed: ${++count}`); if (count === 3) clearInterval(intervalId); }, 500);
6. Fermer la phase de rappels
Cette phase gère les opérations de nettoyage. Par exemple, les rappels associés à la fermeture des connexions réseau, tels que socket.on('close'), sont exécutés ici.
const fs = require('fs'); fs.readFile('file.txt', (err, data) => { if (err) console.error(err); else console.log(data.toString()); });
Sortie :
Read operation scheduled. File content:<contents of example.txt>
Lorsque le client se déconnecte, le rappel socket.on('close') est exécuté dans la phase de rappel de fermeture.
Bien que la boucle d'événements soit conçue pour gérer efficacement les opérations asynchrones, le blocage de la boucle peut dégrader les performances. Si le thread principal est bloqué par des calculs lourds ou des opérations synchrones, il empêche l'exécution d'autres rappels. Cela peut entraîner des retards et rendre votre candidature sans réponse.
Lorsque vous effectuez des tâches gourmandes en CPU (comme des calculs volumineux) sur le thread principal, cela bloque la boucle d'événements. Voici comment utiliser Worker Threads pour éviter le blocage.
Exemple de blocage de la boucle d'événement
const net = require('net'); const server = net.createServer((socket) => { socket.end('Connection closed.'); }); server.listen(8080, () => { console.log('Server listening on port 8080.'); });
Sortie :
const http = require('http'); const server = http.createServer((req, res) => { res.end('Hello from server!'); }); server.listen(3000, () => { console.log('Server running on http://localhost:3000'); });
Dans cet exemple, rien d'autre ne peut s'exécuter pendant la période de blocage de 5 secondes, ce qui rend l'application insensible.
Solution : Utiliser des threads de travail
setImmediate(() => { console.log('Executed in check phase.'); }); setTimeout(() => { console.log('Executed in timers phase.'); }, 0); console.log('Main code executed.');
Sortie :
Main code executed. Executed in check phase. Executed in timers phase.
Ici, le calcul du blocage s'exécute dans un thread séparé, laissant la boucle d'événements libre pour gérer d'autres tâches.
Node.js fournit le module Worker Threads pour gérer des tâches telles que le traitement d'images, le cryptage ou les calculs complexes. Cela permet d'exécuter des opérations lourdes en parallèle, déchargeant ainsi le travail de la boucle d'événements.
Exemple de thread de travail :
setTimeout(() => { console.log('Executed after 1 second.'); }, 1000); console.log('Timer scheduled.');
Utilisez des fonctions asynchrones ou setImmediate pour diviser une tâche volumineuse en opérations plus petites et non bloquantes.
Exemple :
Timer scheduled. Executed after 1 second.
La boucle d'événements est un composant central de Node.js, responsable de la gestion efficace des opérations asynchrones. En comprenant ses six phases : Minuteries, Rappels en attente, Inactivité et préparation, Sondage, Vérification, et Fermer les rappels, les développeurs peuvent écrire du code non bloquant qui fonctionne correctement. Cependant, il est crucial d’éviter de bloquer la boucle d’événements avec des calculs lourds. L'utilisation d'outils tels que Worker Threads garantit que votre application reste rapide et réactive. La maîtrise de la boucle d'événements vous permettra de créer des applications Node.js évolutives et performantes.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!