Table des matières
Qu'est-ce qu'un événement ?
Qu'est-ce qu'EventEmitter ? La classe
Créer des EventEmitters
de l'objet EventEmitter
eventNames()
removeListener()
removeAllListeners()
错误处理
使用 EventEmitter 的原生模块
Résumé
Maison interface Web js tutoriel Comment utiliser EventEmitter pour gérer les événements dans Node.js ?

Comment utiliser EventEmitter pour gérer les événements dans Node.js ?

Nov 02, 2020 pm 05:46 PM
node.js 前端

Comment utiliser EventEmitter pour gérer les événements dans Node.js ?

Dans ce tutoriel, nous découvrons la classe EvenEmitter native de Node.js. Après avoir appris, vous comprendrez les événements, comment utiliser EvenEmitter et comment utiliser les événements dans vos programmes. De plus, vous apprendrez également comment la classe EventEmitter s'étend à partir d'autres modules locaux et comprendrez les principes qui la sous-tendent à travers quelques exemples.

Tutoriel recommandé : tutoriel node js

En bref, cet article couvre tout sur la classe EventEmitter.

Qu'est-ce qu'un événement ?

L'architecture basée sur les événements est très courante aujourd'hui. Les programmes basés sur les événements peuvent générer, détecter et répondre à divers événements.

La partie centrale de Node.js est pilotée par les événements, et de nombreux modules tels que le système de fichiers (fs) et stream sont eux-mêmes écrits en utilisant EventEmitter.

Dans la programmation événementielle, un événement est le résultat d'une ou plusieurs actions, qui peuvent être une opération d'un utilisateur ou la sortie de synchronisation d'un capteur, etc.

Nous pouvons considérer les programmes événementiels comme un modèle de publication-abonnement, dans lequel les éditeurs déclenchent des événements et les abonnés écoutent les événements et prennent les mesures appropriées.

Par exemple, imaginez qu'il existe un serveur sur lequel les utilisateurs peuvent télécharger des images. En programmation événementielle, une action telle que télécharger une image émettra un événement, qui aura également 1 à n abonnés afin d'en profiter.

Une fois l'événement de téléchargement déclenché, un abonné peut le faire savoir et réagir à l'administrateur du site en envoyant un e-mail à l'administrateur du site ; un autre abonné peut collecter des informations sur l'action et les enregistrer dans la base de données.

Ces événements sont généralement indépendants les uns des autres, bien qu'ils puissent également être dépendants les uns des autres.

Qu'est-ce qu'EventEmitter ? La classe

EventEmitter est une classe intégrée de Node.js, située dans le module events. Selon la description dans la documentation :

La plupart des API principales de Node.js sont implémentées sur la base d'une architecture événementielle asynchrone idiomatique, dans laquelle certains types d'objets (appelés " émetteur ») émettent des événements nommés qui provoquer des appels à des Function objets ("auditeurs")"

Cette classe peut à certains égards être décrite comme une implémentation d'un assistant pour le modèle de publication-abonnement, car elle peut aider les émetteurs d'événements (éditeurs) à publier des événements (messages) aux auditeurs (abonnés) de manière simple

Créer des EventEmitters

Cela dit, faisons-le d'abord. Créer un EventEmitter est plus pratique, soit en créant une instance. de la classe elle-même ou en implémentant une classe personnalisée, puis en créant un objet

de l'objet EventEmitter

Commencez par un exemple simple : créez un

qui émet un. événement contenant des informations d'exécution du programme chaque seconde EventEmitter

Importez d'abord la classe

depuis le module events : EventEmitter

const { EventEmitter } = require('events');
Copier après la connexion
Créez ensuite un

 : EventEmitter

const timerEventEmitter = new EventEmitter();
Copier après la connexion
. est très simple de publier un événement avec cet objet :

timerEventEmitter.emit("update");
Copier après la connexion
Le nom de l'événement a été précisé précédemment et il est publié en tant qu'événement. Le programme n'a pas de réponse car aucun auditeur n'a encore réagi à cet événement

Laissez d'abord cet événement se répéter toutes les secondes. Utilisez la méthode

pour créer une minuterie et publiez-la toutes les secondes. Événement :

let currentTime = 0;

// 每秒触发一次 update 事件
setInterval(() => {
    currentTime++;
    timerEventEmitter.emit('update', currentTime);
}, 1000);
Copier après la connexion
setInterval()update est utilisée pour accepter le nom et les paramètres de l'événement. Passez comme nom de l'événement et

comme heure depuis le démarrage du programme. La méthode 🎜> déclenche l'émetteur, qui transmet l'événement avec les informations que nous avons fournies. Après avoir préparé l'émetteur d'événement, abonnez-vous à l'écouteur d'événement pour. it : EventEmitter

timerEventEmitter.on('update', (time) => {
    console.log('从发布者收到的消息:');
    console.log(`程序已经运行了 ${time} 秒`);
});
Copier après la connexion
updateCréez l'écouteur via la méthode currentTime et transmettez-le. Le nom de l'événement pour spécifier à quel événement vous souhaitez attacher l'écouteur. Sur l'événement , exécutez une méthode qui enregistre le. time. Le deuxième paramètre de la fonction

emit()

est un rappel qui peut être accepté

on()L'exécution du code affichera : update

从发布者收到的消息:
程序已经运行了 1 秒
从发布者收到的消息:
程序已经运行了 2 秒
从发布者收到的消息:
程序已经运行了 3 秒
...
Copier après la connexion
Si vous avez seulement besoin d'effectuer. certaines opérations lorsque l'événement est déclenché pour la première fois, vous pouvez également utiliser la méthode

pour vous abonner : on()

timerEventEmitter.once('update', (time) => {
    console.log('从发布者收到的消息:');
    console.log(`程序已经运行了 ${time} 秒`);
});
Copier après la connexion
L'exécution de ce code affichera :

从发布者收到的消息:
程序已经运行了 1 秒
Copier après la connexion

EventEmitteronce() Avec plusieurs auditeurs

Voici un autre programme émetteur d'événements, il y a trois auditeurs, le premier auditeur met à jour l'heure toutes les secondes, le deuxième auditeur se déclenche lorsque le timer est sur le point de se terminer, et le dernier. se déclenche lorsque le timer est terminé :

: Déclenche une fois par seconde

: Déclenche à la fin du compte à rebours
  • update : Déclenchez 2 secondes avant la fin du compte à rebours
  • end d'abord Écrivez une fonction qui crée cet émetteur d'événement :
const countDown = (countdownTime) => {
    const eventEmitter = new EventEmitter();

    let currentTime = 0;

    // 每秒触发一次 update 事件
    const timer = setInterval(() => {
        currentTime++;
        eventEmitter.emit('update', currentTime);

        // 检查计时是否已经结束
        if (currentTime === countdownTime) {
            clearInterval(timer);
            eventEmitter.emit('end');
        }

        // 检查计时是否会在 2 秒后结束
        if (currentTime === countdownTime - 2) {
            eventEmitter.emit('end-soon');
        }
    }, 1000);
    return eventEmitter;
};
Copier après la connexion

这个函数启动了一个每秒钟发出一次 update 事件的事件。

第一个 if 用来检查计时是否已经结束并停止基于间隔的事件。如果已结束将会发布 end 事件。

如果计时没有结束,那么就检查计时是不是离结束还有 2 秒,如果是则发布 end-soon 事件。

向该事件发射器添加一些订阅者:

const myCountDown = countDown(5);

myCountDown.on('update', (t) => {
    console.log(`程序已经运行了 ${t} 秒`);
});

myCountDown.on('end', () => {
    console.log('计时结束');
});

myCountDown.on('end-soon', () => {
    console.log('计时将在2秒后结束');
});
Copier après la connexion

这段代码将会输出:

程序已经运行了 1 秒
程序已经运行了 2 秒
程序已经运行了 3 秒
计时将在2秒后结束
程序已经运行了 4 秒
程序已经运行了 5 秒
计时结束
Copier après la connexion
Copier après la connexion

扩展 EventEmitter

接下来通过扩展 EventEmitter 类来实现相同的功能。首先创建一个处理事件的 CountDown 类:

const { EventEmitter } = require('events');

class CountDown extends EventEmitter {
    constructor(countdownTime) {
        super();
        this.countdownTime = countdownTime;
        this.currentTime = 0;
    }

    startTimer() {
        const timer = setInterval(() => {
            this.currentTime++;
            this.emit('update', this.currentTime);
    
            // 检查计时是否已经结束
            if (this.currentTime === this.countdownTime) {
                clearInterval(timer);
                this.emit('end');
            }
    
            // 检查计时是否会在 2 秒后结束
            if (this.currentTime === this.countdownTime - 2) {
                this.emit('end-soon');
            }
        }, 1000);
    }
}
Copier après la connexion

可以在类的内部直接使用 this.emit()。另外 startTimer() 函数用于控制计时开始的时间。否则它将在创建对象后立即开始计时。

创建一个 CountDown 的新对象并订阅它:

const myCountDown = new CountDown(5);

myCountDown.on('update', (t) => {
    console.log(`计时开始了 ${t} 秒`);
});

myCountDown.on('end', () => {
    console.log('计时结束');
});

myCountDown.on('end-soon', () => {
    console.log('计时将在2秒后结束');
});

myCountDown.startTimer();
Copier après la connexion

运行程序会输出:

程序已经运行了 1 秒
程序已经运行了 2 秒
程序已经运行了 3 秒
计时将在2秒后结束
程序已经运行了 4 秒
程序已经运行了 5 秒
计时结束
Copier après la connexion
Copier après la connexion

on() 函数的别名是 addListener()。看一下 end-soon 事件监听器:

myCountDown.on('end-soon', () => {
    console.log('计时将在2秒后结束');
});
Copier après la connexion

也可以用 addListener() 来完成相同的操作,例如:

myCountDown.addListener('end-soon', () => {
    console.log('计时将在2秒后结束');
});
Copier après la connexion

EventEmitter 的主要函数

eventNames()

此函数将以数组形式返回所有活动的侦听器名称:

const myCountDown = new CountDown(5);

myCountDown.on('update', (t) => {
    console.log(`程序已经运行了 ${t} 秒`);
});

myCountDown.on('end', () => {
    console.log('计时结束');
});

myCountDown.on('end-soon', () => {
    console.log('计时将在2秒后结束');
});

console.log(myCountDown.eventNames());
Copier après la connexion

运行这段代码会输出:

[ 'update', 'end', 'end-soon' ]
Copier après la connexion

如果要订阅另一个事件,例如 myCount.on('some-event', ...),则新事件也会添加到数组中。

这个方法不会返回已发布的事件,而是返回订阅的事件的列表。

removeListener()

这个函数可以从 EventEmitter 中删除已订阅的监听器:

const { EventEmitter } = require('events');

const emitter = new EventEmitter();

const f1 = () => {
    console.log('f1 被触发');
}

const f2 = () => {
    console.log('f2 被触发');
}

emitter.on('some-event', f1);
emitter.on('some-event', f2);

emitter.emit('some-event');

emitter.removeListener('some-event', f1);

emitter.emit('some-event');
Copier après la connexion

在第一个事件触发后,由于 f1f2 都处于活动状态,这两个函数都将被执行。之后从 EventEmitter 中删除了 f1。当再次发出事件时,将会只执行 f2

f1 被触发
f2 被触发
f2 被触发
Copier après la connexion

An alias for removeListener() is off(). For example, we could have written:

removeListener() 的别名是 off()。例如可以这样写:

emitter.off('some-event', f1);
Copier après la connexion

removeAllListeners()

该函数用于从 EventEmitter 的所有事件中删除所有侦听器:

const { EventEmitter } = require('events');

const emitter = new EventEmitter();

const f1 = () => {
    console.log('f1 被触发');
}

const f2 = () => {
    console.log('f2 被触发');
}

emitter.on('some-event', f1);
emitter.on('some-event', f2);

emitter.emit('some-event');

emitter.removeAllListeners();

emitter.emit('some-event');
Copier après la connexion

第一个 emit() 会同时触发 f1f2,因为它们当时正处于活动状态。删除它们后,emit() 函数将发出事件,但没有侦听器对此作出响应:

f1 被触发
f2 被触发
Copier après la connexion

错误处理

如果要在 EventEmitter 发出错误,必须用 error 事件名来完成。这是 Node.js 中所有 EventEmitter 对象的标准配置。这个事件必须还要有一个 Error 对象。例如可以像这样发出错误事件:

myEventEmitter.emit('error', new Error('出现了一些错误'));
Copier après la connexion

error 事件的侦听器都应该有一个带有一个参数的回调,用来捕获 Error 对象并处理。如果 EventEmitter 发出了 error 事件,但是没有订阅者订阅 error 事件,那么 Node.js 程序将会抛出这个 Error。这会导致 Node.js 进程停止运行并退出程序,同时在控制台中显示这个错误的跟踪栈。

例如在 CountDown 类中,countdownTime参数的值不能小于 2,否则会无法触发 end-soon 事件。在这种情况下应该发出一个 error 事件:

class CountDown extends EventEmitter {
    constructor(countdownTime) {
        super();

        if (countdownTimer < 2) {
            this.emit(&#39;error&#39;, new Error(&#39;countdownTimer 的值不能小于2&#39;));
        }

        this.countdownTime = countdownTime;
        this.currentTime = 0;
    }

    // ...........
}
Copier après la connexion

处理这个错误的方式与其他事件相同:

myCountDown.on(&#39;error&#39;, (err) => {
    console.error('发生错误:', err);
});
Copier après la connexion

始终对 error 事件进行监听是一种很专业的做法。

使用 EventEmitter 的原生模块

Node.js 中许多原生模块扩展了EventEmitter 类,因此它们本身就是事件发射器。

一个典型的例子是 Stream 类。官方文档指出:

流可以是可读的、可写的,或两者均可。所有流都是 EventEmitter 的实例。

先看一下经典的 Stream 用法:

const fs = require('fs');
const writer = fs.createWriteStream('example.txt');

for (let i = 0; i < 100; i++) {
  writer.write(`hello, #${i}!\n`);
}

writer.on(&#39;finish&#39;, () => {
  console.log('All writes are now complete.');
});

writer.end('This is the end\n');
Copier après la connexion

但是,在写操作和 writer.end() 调用之间,我们添加了一个侦听器。 Stream 在完成后会发出一个 finished 事件。在发生错误时会发出 error 事件,把读取流通过管道传输到写入流时会发出 pipe 事件,从写入流中取消管道传输时,会发出 unpipe 事件。

另一个类是 child_process 类及其 spawn() 方法:

const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});
Copier après la connexion

当  child_process 写入标准输出管道时,将会触发  stdoutdata 事件。当输出流遇到错误时,将从 stderr 管道发送 data 事件。

Enfin, une fois le processus terminé, l'événement close sera déclenché.

Résumé

L'architecture événementielle nous permet de créer des systèmes avec une cohésion élevée et un faible couplage. Un événement représente le résultat d'une action, et un ou plusieurs auditeurs peuvent être définis et y réagir.

Cet article examine en profondeur la classe EventEmitter et ses fonctionnalités. Instanciez-le et utilisez-le directement, et étendez son comportement dans un objet personnalisé.

Enfin, quelques fonctions importantes de cette classe sont introduites.

Pour plus de connaissances liées à la programmation, veuillez visiter : Cours de programmation ! !

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!

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

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

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)

PHP et Vue : une combinaison parfaite d'outils de développement front-end PHP et Vue : une combinaison parfaite d'outils de développement front-end Mar 16, 2024 pm 12:09 PM

PHP et Vue : une combinaison parfaite d'outils de développement front-end À l'ère actuelle de développement rapide d'Internet, le développement front-end est devenu de plus en plus important. Alors que les utilisateurs ont des exigences de plus en plus élevées en matière d’expérience des sites Web et des applications, les développeurs front-end doivent utiliser des outils plus efficaces et plus flexibles pour créer des interfaces réactives et interactives. En tant que deux technologies importantes dans le domaine du développement front-end, PHP et Vue.js peuvent être considérés comme une arme parfaite lorsqu'ils sont associés. Cet article explorera la combinaison de PHP et Vue, ainsi que des exemples de code détaillés pour aider les lecteurs à mieux comprendre et appliquer ces deux éléments.

Comment utiliser le langage Go pour le développement front-end ? Comment utiliser le langage Go pour le développement front-end ? Jun 10, 2023 pm 05:00 PM

Avec le développement de la technologie Internet, le développement front-end est devenu de plus en plus important. La popularité des appareils mobiles, en particulier, nécessite une technologie de développement frontal efficace, stable, sûre et facile à entretenir. En tant que langage de programmation en développement rapide, le langage Go est utilisé par de plus en plus de développeurs. Alors, est-il possible d’utiliser le langage Go pour le développement front-end ? Ensuite, cet article expliquera en détail comment utiliser le langage Go pour le développement front-end. Voyons d’abord pourquoi le langage Go est utilisé pour le développement front-end. Beaucoup de gens pensent que le langage Go est un

Questions fréquemment posées par les enquêteurs front-end Questions fréquemment posées par les enquêteurs front-end Mar 19, 2024 pm 02:24 PM

Lors des entretiens de développement front-end, les questions courantes couvrent un large éventail de sujets, notamment les bases HTML/CSS, les bases JavaScript, les frameworks et les bibliothèques, l'expérience du projet, les algorithmes et les structures de données, l'optimisation des performances, les requêtes inter-domaines, l'ingénierie front-end, les modèles de conception et les nouvelles technologies et tendances. Les questions de l'intervieweur sont conçues pour évaluer les compétences techniques du candidat, son expérience en matière de projet et sa compréhension des tendances du secteur. Par conséquent, les candidats doivent être parfaitement préparés dans ces domaines pour démontrer leurs capacités et leur expertise.

Django est-il front-end ou back-end ? Vérifiez-le! Django est-il front-end ou back-end ? Vérifiez-le! Jan 19, 2024 am 08:37 AM

Django est un framework d'application Web écrit en Python qui met l'accent sur un développement rapide et des méthodes propres. Bien que Django soit un framework Web, pour répondre à la question de savoir si Django est un front-end ou un back-end, vous devez avoir une compréhension approfondie des concepts de front-end et de back-end. Le front-end fait référence à l'interface avec laquelle les utilisateurs interagissent directement, et le back-end fait référence aux programmes côté serveur. Ils interagissent avec les données via le protocole HTTP. Lorsque le front-end et le back-end sont séparés, les programmes front-end et back-end peuvent être développés indépendamment pour mettre en œuvre respectivement la logique métier et les effets interactifs, ainsi que l'échange de données.

Golang peut-il être utilisé comme frontal ? Golang peut-il être utilisé comme frontal ? Jun 06, 2023 am 09:19 AM

Golang peut être utilisé comme frontal. Golang est un langage de programmation très polyvalent qui peut être utilisé pour développer différents types d'applications, y compris des applications frontales. En utilisant Golang pour écrire le front-end, vous pouvez vous débarrasser d'un front-end. série de problèmes causés par des langages tels que JavaScript. Par exemple, des problèmes tels qu'une mauvaise sécurité des types, de faibles performances et un code difficile à maintenir.

Partage d'expérience en développement C# : compétences en développement collaboratif front-end et back-end Partage d'expérience en développement C# : compétences en développement collaboratif front-end et back-end Nov 23, 2023 am 10:13 AM

En tant que développeur C#, notre travail de développement comprend généralement le développement front-end et back-end. À mesure que la technologie se développe et que la complexité des projets augmente, le développement collaboratif du front-end et du back-end est devenu de plus en plus important et complexe. Cet article partagera quelques techniques de développement collaboratif front-end et back-end pour aider les développeurs C# à effectuer leur travail de développement plus efficacement. Après avoir déterminé les spécifications de l’interface, le développement collaboratif du front-end et du back-end est indissociable de l’interaction des interfaces API. Pour assurer le bon déroulement du développement collaboratif front-end et back-end, le plus important est de définir de bonnes spécifications d’interface. La spécification de l'interface implique le nom de l'interface

Explorer la technologie front-end du langage Go : une nouvelle vision du développement front-end Explorer la technologie front-end du langage Go : une nouvelle vision du développement front-end Mar 28, 2024 pm 01:06 PM

En tant que langage de programmation rapide et efficace, le langage Go est très populaire dans le domaine du développement back-end. Cependant, peu de gens associent le langage Go au développement front-end. En fait, l’utilisation du langage Go pour le développement front-end peut non seulement améliorer l’efficacité, mais également ouvrir de nouveaux horizons aux développeurs. Cet article explorera la possibilité d'utiliser le langage Go pour le développement front-end et fournira des exemples de code spécifiques pour aider les lecteurs à mieux comprendre ce domaine. Dans le développement front-end traditionnel, JavaScript, HTML et CSS sont souvent utilisés pour créer des interfaces utilisateur.

Comment implémenter la messagerie instantanée sur le front-end Comment implémenter la messagerie instantanée sur le front-end Oct 09, 2023 pm 02:47 PM

Les méthodes de mise en œuvre de la messagerie instantanée incluent WebSocket, Long Polling, Server-Sent Events, WebRTC, etc. Introduction détaillée : 1. WebSocket, qui peut établir une connexion persistante entre le client et le serveur pour obtenir une communication bidirectionnelle en temps réel. Le frontal peut utiliser l'API WebSocket pour créer une connexion WebSocket et obtenir une messagerie instantanée en envoyant et en recevant. messages 2. Long Polling, une technologie qui simule la communication en temps réel, etc.

See all articles