Maison interface Web js tutoriel Explication détaillée de la boucle d'événements Node.js (Event Loop) et du thread pool_node.js

Explication détaillée de la boucle d'événements Node.js (Event Loop) et du thread pool_node.js

May 16, 2016 pm 04:17 PM
event loop node.js 事件循环 线程池

La « boucle d'événement » de Node est au cœur de sa capacité à gérer une grande concurrence et un débit élevé. C'est la partie la plus magique, selon laquelle Node.js peut fondamentalement être compris comme "mono-thread", tout en permettant également de traiter des opérations arbitraires en arrière-plan. Cet article clarifiera le fonctionnement de la boucle d'événements afin que vous puissiez ressentir sa magie.

Programmation événementielle

Pour comprendre la boucle d'événements, vous devez d'abord comprendre la programmation pilotée par les événements. Il est apparu en 1960. De nos jours, la programmation événementielle est largement utilisée dans la programmation de l’interface utilisateur. L'une des principales utilisations de JavaScript est d'interagir avec le DOM, il est donc naturel d'utiliser une API basée sur les événements.

Défini simplement : la programmation basée sur les événements contrôle le flux d'une application à travers des événements ou des changements d'état. Généralement mis en œuvre via la surveillance d'événements, une fois l'événement détecté (c'est-à-dire que l'état change), la fonction de rappel correspondante est appelée. Cela vous semble familier ? En fait, c'est le principe de fonctionnement de base de la boucle d'événements Node.js.

Si vous êtes familier avec le développement JavaScript côté client, pensez aux méthodes .on*(), telles que element.onclick(), qui sont utilisées pour se combiner avec des éléments DOM pour offrir une interaction utilisateur. Ce mode de fonctionnement permet de déclencher plusieurs événements sur une seule instance. Node.js déclenche ce modèle via des EventEmitters (générateurs d'événements), comme dans les modules Socket et "http" côté serveur. Un ou plusieurs changements d'état peuvent être déclenchés à partir d'une seule instance.

Un autre schéma courant consiste à exprimer le succès et l’échec. Il existe généralement deux méthodes de mise en œuvre courantes. La première consiste à transmettre « l'exception d'erreur » dans le rappel, généralement comme premier paramètre de la fonction de rappel. Le second utilise le modèle de conception Promises et a ajouté ES6. Remarque* Le mode Promesse utilise une méthode d'écriture de chaîne de fonctions similaire à jQuery pour éviter une imbrication profonde des fonctions de rappel, telles que :

Copier le code Le code est le suivant :

$.getJSON('/getUser').done(successHandler).fail(failHandler)

Le module "fs" (système de fichiers) adopte principalement le style de transmission des exceptions dans les rappels. Déclenchant techniquement certains appels, comme l'événement attaché fs.readFile(), mais l'API sert simplement à alerter l'utilisateur et à exprimer le succès ou l'échec de l'opération. Le choix d'une telle API repose sur des considérations architecturales plutôt que sur des limitations techniques.

Une idée fausse courante est que les émetteurs d'événements sont également intrinsèquement asynchrones lors du déclenchement d'événements, mais c'est incorrect. Vous trouverez ci-dessous un simple extrait de code pour le démontrer.

Copier le code Le code est le suivant :

fonction MonEmitter() {
EventEmitter.call(this);
>
util.inherits(MyEmitter, EventEmitter);

MyEmitter.prototype.doStuff = function doStuff() {
console.log('avant')
émetteur.emit('feu')
console.log('after')}
};

var me = new MyEmitter();
moi.on('fire', function() {
console.log('emit Fire');
});

me.doStuff();
// Sortie :
// avant
// émet tiré
// après

Remarque* Si émetteur.emit est asynchrone, la sortie doit être
// avant
// après
// émet tiré


EventEmitter se comporte souvent de manière asynchrone car il est souvent utilisé pour notifier les opérations qui doivent être effectuées de manière asynchrone, mais l'API EventEmitter elle-même est entièrement synchrone. Les fonctions d'écoute peuvent être exécutées de manière asynchrone en interne, mais veuillez noter que toutes les fonctions d'écoute seront exécutées de manière synchrone dans l'ordre dans lequel elles sont ajoutées.

Aperçu du mécanisme et pool de threads

Node lui-même repose sur plusieurs bibliothèques. L'un d'eux est libuv, l'étonnante bibliothèque permettant de gérer les files d'attente et l'exécution d'événements asynchrones.

Node utilise autant que possible le noyau du système d'exploitation pour implémenter les fonctions existantes. Comme générer des demandes de réponse, transférer les connexions et les confier au système pour traitement. Par exemple, les connexions entrantes sont mises en file d'attente via le système d'exploitation jusqu'à ce qu'elles puissent être gérées par Node.

Vous avez peut-être entendu dire que Node dispose d'un pool de threads, et vous vous demandez peut-être : "Si Node traite les tâches dans l'ordre, pourquoi avons-nous besoin d'un pool de threads ?" commande exécutée de manière asynchrone. Dans ce cas, Node.JS doit être capable de verrouiller le thread pendant un certain temps pendant son fonctionnement afin qu'il puisse continuer à exécuter la boucle d'événements sans être bloqué.

Ce qui suit est un exemple de schéma simple pour montrer son mécanisme de fonctionnement interne :


┌──────────────────────┐
╭──►│ minuteries minuteries │        └───────────┬───────────┘
│       ┌───────────┴───────────┐
│                                                                                                                                                                                                                                   rappels en attente                                           │          └──────────┬───────────┘                                                                                                                                                                         | │ │ │ SONDAGE ││── Connexions, │
│                                                                                                                                                                                                                                                        depuis │           ┌───────────┴───────────┐                                                                                                                                              ╰─── ┤ setImmédiat └───────────────────────┘

Il y a certaines choses difficiles à comprendre concernant le fonctionnement interne de la boucle événementielle :

Tous les rappels seront prédéfinis via process.nextTick() à la fin d'une étape de la boucle d'événement (par exemple, une minuterie) et avant de passer à l'étape suivante. Cela évitera les appels récursifs potentiels à process.nextTick(), provoquant une boucle infinie.
Les « rappels en attente » sont des rappels dans la file d'attente de rappel qui ne seront traités par aucun autre cycle de boucle d'événement (par exemple, transmis à fs.write).

Émetteur d'événement et boucle d'événement

Simplifiez l'interaction avec la boucle d'événements en créant un EventEmitter. Il s'agit d'un wrapper générique qui vous permet de créer plus facilement des API basées sur des événements. La façon dont les deux interagissent laisse souvent les développeurs confus.

L'exemple suivant montre qu'oublier qu'un événement est déclenché de manière synchrone peut entraîner la perte de l'événement.

Copier le code Le code est le suivant :

// Après la v0.10, require('events').EventEmitter n'est plus nécessaire
var EventEmitter = require('events');
var util = require('util');

fonction MyThing() {
EventEmitter.call(this);

doFirstThing();
this.emit('thing1');
>
util.inherits(MyThing, EventEmitter);

var mt = new MyThing();

mt.on('thing1', function onThing1() {
// Désolé, cet événement n'arrivera jamais
});


L'événement 'thing1' ci-dessus ne sera jamais capturé par MyThing() car MyThing() doit être instancié avant de pouvoir écouter les événements. Voici une solution de contournement simple sans ajouter de fermetures supplémentaires :
Copier le code Le code est le suivant :

var EventEmitter = require('events');
var util = require('util');

fonction MyThing() {
EventEmitter.call(this);

doFirstThing();
setImmediate(emitThing1, this);
>
util.inherits(MyThing, EventEmitter);

fonction émetThing1(self) {
self.emit('thing1');
>

var mt = new MyThing();

mt.on('thing1', function onThing1() {
// Exécuté
});

La solution suivante fonctionnera également, mais au détriment de certaines performances :

Copier le code Le code est le suivant :

fonction MyThing() {
EventEmitter.call(this);

doFirstThing();
// L'utilisation de Function#bind() perdra en performances
setImmediate(this.emit.bind(this, 'thing1'));
>
util.inherits(MyThing, EventEmitter);


Un autre problème est le déclenchement d’une erreur. Trouver des problèmes dans votre application est déjà assez difficile, mais sans la pile d'appels (note *e.stack), le débogage est presque impossible. Lorsqu'une erreur est reçue par une requête asynchrone distante, la pile d'appels sera perdue. Il existe deux solutions possibles : déclencher de manière synchrone ou garantir que l'erreur est transmise avec d'autres informations importantes. Les exemples ci-dessous illustrent les deux solutions :
Copier le code Le code est le suivant :

MyThing.prototype.foo = function foo() {
// Cette erreur sera déclenchée de manière asynchrone
var euh = doFirstThing();
si (euh) {
//Lorsqu'elle est déclenchée, une nouvelle erreur doit être créée pour conserver les informations de la pile d'appels sur site
setImmediate(emitError, this, new Error('Bad stuff'));
Retour ;
>

// Déclenchez une erreur et gérez-la immédiatement (de manière synchrone)
var euh = doSecondThing();
si (euh) {
This.emit('erreur', 'Plus de mauvaises choses');
Retour ;
>
>


Évaluez la situation. Lorsqu'une erreur est déclenchée, elle peut être traitée immédiatement. Ou bien, il peut s’agir d’une exception triviale qui peut être facilement gérée ou traitée plus tard. De plus, transmettre Error via un constructeur n'est pas une bonne idée, car l'instance d'objet construite est probablement incomplète. Le cas où Error a été lancé directement tout à l'heure est une exception.

Conclusion

Cet article aborde brièvement le fonctionnement interne et les détails techniques de la boucle d'événements. Tout est bien pensé. Un autre article discutera de l'interaction de la boucle d'événements avec le noyau du système et montrera la magie du fonctionnement asynchrone de NodeJS.

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

Repo: Comment relancer ses coéquipiers
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Un article pour parler du contrôle de la mémoire dans Node Un article pour parler du contrôle de la mémoire dans Node Apr 26, 2023 pm 05:37 PM

Le service Node construit sur une base non bloquante et piloté par les événements présente l'avantage d'une faible consommation de mémoire et est très adapté à la gestion de requêtes réseau massives. Dans le contexte de demandes massives, les questions liées au « contrôle de la mémoire » doivent être prises en compte. 1. Le mécanisme de récupération de place du V8 et les limitations de mémoire Js sont contrôlés par la machine de récupération de place

Parlons en profondeur du module File dans Node Parlons en profondeur du module File dans Node Apr 24, 2023 pm 05:49 PM

Le module de fichiers est une encapsulation des opérations de fichiers sous-jacentes, telles que l'ajout de lecture/écriture/ouverture/fermeture/suppression de fichiers, etc. La plus grande caractéristique du module de fichiers est que toutes les méthodes fournissent deux versions de **synchrone** et ** asynchrone**, with Les méthodes avec le suffixe sync sont toutes des méthodes de synchronisation, et celles qui n'en ont pas sont toutes des méthodes hétérogènes.

En savoir plus sur les tampons dans Node En savoir plus sur les tampons dans Node Apr 25, 2023 pm 07:49 PM

Au début, JS ne fonctionnait que du côté du navigateur. Il était facile de traiter les chaînes codées en Unicode, mais il était difficile de traiter les chaînes binaires et non codées en Unicode. Et le binaire est le format de données le plus bas du package ordinateur, vidéo/audio/programme/réseau.

Comment utiliser le pool de threads pour implémenter la planification circulaire des tâches dans Java 7 Comment utiliser le pool de threads pour implémenter la planification circulaire des tâches dans Java 7 Jul 29, 2023 pm 10:37 PM

Comment utiliser des pools de threads pour implémenter la planification cyclique des tâches dans Java 7 Introduction : lors du développement d'applications Java, l'utilisation de pools de threads peut améliorer l'efficacité de l'exécution des tâches et l'utilisation des ressources. En Java7, le pool de threads peut être utilisé pour implémenter facilement une planification circulaire des tâches. Cet article expliquera comment utiliser les pools de threads pour implémenter la planification circulaire des tâches dans Java7 et joindra des exemples de code correspondants. 1. Présentation : le pool de threads est une structure de traitement multithread qui peut réutiliser un nombre fixe de threads pour éviter la création et la création fréquentes.

Problèmes courants de charge de serveur sous les systèmes Linux et leurs solutions Problèmes courants de charge de serveur sous les systèmes Linux et leurs solutions Jun 18, 2023 am 09:22 AM

Linux est un excellent système d'exploitation largement utilisé dans les systèmes serveurs. Lors de l'utilisation des systèmes Linux, les problèmes de charge du serveur sont un phénomène courant. La charge du serveur signifie que les ressources système du serveur ne peuvent pas satisfaire les demandes actuelles, ce qui rend la charge du système trop élevée, affectant ainsi les performances du serveur. Cet article présentera les problèmes courants de charge de serveur et leurs solutions sous les systèmes Linux. 1. La charge du processeur est trop élevée. Lorsque la charge du processeur du serveur est trop élevée, cela entraînera des problèmes tels qu'une réponse plus lente du système et un temps de traitement des requêtes plus long. Quand C

Bibliothèque de traitement d'événements en PHP8.0 : Événement Bibliothèque de traitement d'événements en PHP8.0 : Événement May 14, 2023 pm 05:40 PM

Bibliothèque de traitement d'événements en PHP8.0 : Événement Avec le développement continu d'Internet, PHP, en tant que langage de programmation back-end populaire, est largement utilisé dans le développement de diverses applications Web. Dans ce processus, le mécanisme événementiel est devenu un élément très important. La bibliothèque de traitement d'événements Event en PHP8.0 nous fournira une méthode de traitement d'événements plus efficace et plus flexible. Qu'est-ce que la gestion des événements ? La gestion des événements est un concept très important dans le développement d'applications Web. Les événements peuvent être n'importe quel type de ligne utilisateur

Comment utiliser le pool de threads pour implémenter la planification prioritaire des tâches dans Java 7 Comment utiliser le pool de threads pour implémenter la planification prioritaire des tâches dans Java 7 Jul 30, 2023 pm 06:38 PM

Comment utiliser les pools de threads pour implémenter la planification prioritaire des tâches dans Java7 Dans la programmation simultanée, la planification prioritaire des tâches est une exigence courante. Java fournit un mécanisme de pool de threads qui nous permet de gérer et de planifier facilement des tâches. Cet article explique comment utiliser le pool de threads pour implémenter la planification par priorité des tâches dans Java7. Tout d’abord, nous devons comprendre les concepts de base et l’utilisation des pools de threads en Java7. Un pool de threads est un mécanisme de réutilisation de threads qui gère et planifie un groupe de threads pour effectuer plusieurs tâches. Mention Java

L'ère de l'IA de JS est arrivée ! L'ère de l'IA de JS est arrivée ! Apr 08, 2024 am 09:10 AM

Introduction à JS-Torch JS-Torch est une bibliothèque JavaScript d'apprentissage en profondeur dont la syntaxe est très similaire à celle de PyTorch. Il contient un objet tensoriel entièrement fonctionnel (peut être utilisé avec des dégradés suivis), des couches et des fonctions d'apprentissage en profondeur et un moteur de différenciation automatique. JS-Torch convient à la recherche sur l'apprentissage profond en JavaScript et fournit de nombreux outils et fonctions pratiques pour accélérer le développement de l'apprentissage profond. Image PyTorch est un framework d'apprentissage profond open source développé et maintenu par l'équipe de recherche de Meta. Il fournit un riche ensemble d'outils et de bibliothèques pour créer et former des modèles de réseaux neuronaux. PyTorch est conçu pour être simple, flexible et facile à utiliser, et ses fonctionnalités de graphique de calcul dynamique font

See all articles