EventEmitter を使用して Node.js でイベントを処理するにはどうすればよいですか?
このチュートリアルでは、Node.js のネイティブ EvenEmitter
クラスについて学びます。コースを完了すると、イベント、EvenEmitter
の使用方法、およびプログラムでのイベントの利用方法を理解できるようになります。さらに、EventEmitter
クラスが他のローカル モジュールからどのように拡張されるのかを学び、いくつかの例を通じてその背後にある原則を理解します。
推奨チュートリアル: node js チュートリアル
つまり、この記事では EventEmitter
クラスに関するすべてを説明します。
イベントとは何ですか?
イベント駆動型のアーキテクチャは現在非常に一般的であり、イベント駆動型のプログラムはさまざまなイベントを生成、検出し、それに応答できます。
Node.js のコア部分はイベント駆動型であり、ファイル システム (fs
) や stream
などの多くのモジュール自体が EventEmitter # を使用します。 ## によって書かれた。
Event (event) は、ユーザーの操作やセンサーのタイミング出力など、1 つ以上のアクションの結果です。
イベント駆動型プログラムは、パブリッシャーがイベントをトリガーし、サブスクライバーがイベントをリッスンして適切なアクションを実行する、パブリッシュ/サブスクライブ モデルとして考えることができます。 たとえば、ユーザーが画像をアップロードできるサーバーがあるとします。イベント駆動型プログラミングでは、画像のアップロードなどのアクションによってイベントが発行され、それを利用するために 1 ~ n 人のサブスクライバーも発生します。 アップロード イベントがトリガーされた後、サブスクライバーは、サイトの管理者に電子メールを送信することで、サイトの管理者に通知し、対応することができます。別のサブスクライバーは、アクションに関する情報を収集し、データベースに保存することができます。 これらのイベントは通常、互いに独立していますが、相互に依存する場合もあります。 イベントエミッターとは何ですか?EventEmitter クラスは、
events モジュールにある Node.js の組み込みクラスです。ドキュメントの説明によると:
Function オブジェクト (「リスナー」) への呼び出しが発生します。"
このクラスは、パブリッシュ/サブスクライブ モデルとしてある程度記述することができます。補助ツールの実装は、イベント エミッター ( Create EventEmittersそうは言っても、EventEmitter を作成する方がより現実的です。これを行うには、クラス自体のインスタンスを作成するか、カスタム クラスを通じて実装してから、クラスのインスタンスを作成します。
EventEmitter Object
簡単な例から始めます。プログラムの実行時間情報を含むイベントを毎秒発行するEventEmitter を作成します。
events から開始します。モジュール内の EventEmitter
クラス: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">const { EventEmitter } = require('events');</pre><div class="contentsignin">ログイン後にコピー</div></div>
次に、
: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">const timerEventEmitter = new EventEmitter();</pre><div class="contentsignin">ログイン後にコピー</div></div>
このオブジェクトを使用してイベントを公開します。簡単:
timerEventEmitter.emit("update");
イベント名は以前に指定されており、イベントとして発行されました。しかし、まだこのイベントに反応するリスナーがいないため、プログラムは応答しませんでした。
最初にこのイベントを 1 秒ごとに繰り返します。## を使用してください。 #setInterval()
メソッドを使用してタイマーを作成し、update イベントを 1 秒ごとに発行します:
let currentTime = 0; // 每秒触发一次 update 事件 setInterval(() => { currentTime++; timerEventEmitter.emit('update', currentTime); }, 1000);
EventEmitter インスタンスはイベント名を受け入れるために使用され、パラメータ。イベント名として update を渡し、プログラム開始からの時間として
currentTime を渡します。
emit( )
timerEventEmitter.on('update', (time) => { console.log('从发布者收到的消息:'); console.log(`程序已经运行了 ${time} 秒`); });
via
on() メソッドはリスナーを作成し、イベントを渡しますリスナーをアタッチするイベントを指定する名前。update イベントで、時間を記録するメソッドを実行します。
on()
コードを実行すると、次の出力が出力されます:
从发布者收到的消息: 程序已经运行了 1 秒 从发布者收到的消息: 程序已经运行了 2 秒 从发布者收到的消息: 程序已经运行了 3 秒 ...
once()
メソッドを使用してサブスクライブすることもできます:timerEventEmitter.once('update', (time) => { console.log('从发布者收到的消息:'); console.log(`程序已经运行了 ${time} 秒`); });
このコードを実行すると、出力:
从发布者收到的消息: 程序已经运行了 1 秒
EventEmitter
複数のリスナーを使用する場合以下に別のイベント センダーを作成します。リスナーが3人いるタイマー番組です。最初のリスナーは時間を毎秒更新し、2 番目のリスナーはタイマーが終了するときに起動し、最後のリスナーはタイマーが終了するときに起動します。
update- : 毎秒一度トリガー
-
#end
: カウントダウン終了時にトリガー - #end-soon
: カウントダウン終了の 2 秒前にトリガー
- 最初に、このイベント エミッターを作成する関数を作成します:
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">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; };</pre><div class="contentsignin">ログイン後にコピー</div></div> <p>这个函数启动了一个每秒钟发出一次 <code>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秒后结束'); });
ログイン後にコピー这段代码将会输出:
程序已经运行了 1 秒 程序已经运行了 2 秒 程序已经运行了 3 秒 计时将在2秒后结束 程序已经运行了 4 秒 程序已经运行了 5 秒 计时结束
ログイン後にコピーログイン後にコピー扩展 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); } }
ログイン後にコピー可以在类的内部直接使用
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();
ログイン後にコピー运行程序会输出:
程序已经运行了 1 秒 程序已经运行了 2 秒 程序已经运行了 3 秒 计时将在2秒后结束 程序已经运行了 4 秒 程序已经运行了 5 秒 计时结束
ログイン後にコピーログイン後にコピーon()
函数的别名是addListener()
。看一下end-soon
事件监听器:myCountDown.on('end-soon', () => { console.log('计时将在2秒后结束'); });
ログイン後にコピー也可以用
addListener()
来完成相同的操作,例如:myCountDown.addListener('end-soon', () => { console.log('计时将在2秒后结束'); });
ログイン後にコピー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());
ログイン後にコピー运行这段代码会输出:
[ 'update', 'end', 'end-soon' ]
ログイン後にコピー如果要订阅另一个事件,例如
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');
ログイン後にコピー在第一个事件触发后,由于
f1
和f2
都处于活动状态,这两个函数都将被执行。之后从EventEmitter
中删除了f1
。当再次发出事件时,将会只执行f2
:f1 被触发 f2 被触发 f2 被触发
ログイン後にコピーAn alias for
removeListener()
isoff()
. For example, we could have written:removeListener()
的别名是off()
。例如可以这样写:emitter.off('some-event', f1);
ログイン後にコピー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');
ログイン後にコピー第一个
emit()
会同时触发f1
和f2
,因为它们当时正处于活动状态。删除它们后,emit()
函数将发出事件,但没有侦听器对此作出响应:f1 被触发 f2 被触发
ログイン後にコピー错误处理
如果要在
EventEmitter
发出错误,必须用error
事件名来完成。这是 Node.js 中所有EventEmitter
对象的标准配置。这个事件必须还要有一个Error
对象。例如可以像这样发出错误事件:myEventEmitter.emit('error', new Error('出现了一些错误'));
ログイン後にコピー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('error', new Error('countdownTimer 的值不能小于2')); } this.countdownTime = countdownTime; this.currentTime = 0; } // ........... }
ログイン後にコピー处理这个错误的方式与其他事件相同:
myCountDown.on('error', (err) => { console.error('发生错误:', err); });
ログイン後にコピー始终对
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('finish', () => { console.log('All writes are now complete.'); }); writer.end('This is the end\n');
ログイン後にコピー但是,在写操作和
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}`); });
ログイン後にコピー当
child_process
写入标准输出管道时,将会触发stdout
的data
事件。当输出流遇到错误时,将从stderr
管道发送data
事件。最後に、プロセスが終了すると、
close
イベントがトリガーされます。概要
イベント駆動型アーキテクチャにより、高い凝集性と低い結合性を備えたシステムを作成できます。イベントはアクションの結果を表し、1 つ以上のリスナーを定義してそれに反応できます。
この記事では、
EventEmitter
クラスとその機能について詳しく説明します。インスタンス化して直接使用し、その動作をカスタム オブジェクトに拡張します。最後に、このクラスの重要な機能をいくつか紹介します。
プログラミング関連の知識について詳しくは、プログラミング コースをご覧ください。 !
以上がEventEmitter を使用して Node.js でイベントを処理するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ 今日のインターネットの急速な発展の時代において、フロントエンド開発はますます重要になっています。 Web サイトやアプリケーションのエクスペリエンスに対するユーザーの要求がますます高まっているため、フロントエンド開発者は、より効率的で柔軟なツールを使用して、応答性の高いインタラクティブなインターフェイスを作成する必要があります。フロントエンド開発の分野における 2 つの重要なテクノロジーである PHP と Vue.js は、組み合わせることで完璧なツールと見なされます。この記事では、PHP と Vue の組み合わせと、読者がこれら 2 つをよりよく理解し、適用できるようにするための詳細なコード例について説明します。

インターネット技術の発展に伴い、フロントエンド開発の重要性がますます高まっています。特にモバイル デバイスの人気により、効率的で安定しており、安全で保守が容易なフロントエンド開発テクノロジーが必要です。 Go 言語は、急速に発展しているプログラミング言語として、ますます多くの開発者によって使用されています。では、フロントエンド開発に Go 言語を使用することは可能でしょうか?次に、この記事ではフロントエンド開発にGo言語を使用する方法を詳しく説明します。まずはフロントエンド開発にGo言語が使われる理由を見てみましょう。多くの人は Go 言語は

フロントエンド開発のインタビューでは、HTML/CSS の基本、JavaScript の基本、フレームワークとライブラリ、プロジェクトの経験、アルゴリズムとデータ構造、パフォーマンスの最適化、クロスドメイン リクエスト、フロントエンド エンジニアリング、デザインパターン、新しいテクノロジーとトレンド。面接官の質問は、候補者の技術スキル、プロジェクトの経験、業界のトレンドの理解を評価するように設計されています。したがって、候補者はこれらの分野で自分の能力と専門知識を証明するために十分な準備をしておく必要があります。

Django は、迅速な開発とクリーンなメソッドを重視した Python で書かれた Web アプリケーション フレームワークです。 Django は Web フレームワークですが、Django がフロントエンドなのかバックエンドなのかという質問に答えるには、フロントエンドとバックエンドの概念を深く理解する必要があります。フロントエンドはユーザーが直接対話するインターフェイスを指し、バックエンドはサーバー側プログラムを指し、HTTP プロトコルを通じてデータと対話します。フロントエンドとバックエンドが分離されている場合、フロントエンドとバックエンドのプログラムをそれぞれ独立して開発して、ビジネス ロジックとインタラクティブ効果、およびデータ交換を実装できます。

Golang はフロントエンドとして使用できます。Golang は、フロントエンド アプリケーションなど、さまざまなタイプのアプリケーションの開発に使用できる非常に多用途なプログラミング言語です。Golang を使用してフロントエンドを作成することで、 JavaScript などの言語によって引き起こされる一連の問題、たとえば、型安全性の低さ、パフォーマンスの低下、コードの保守の困難などの問題です。

C# 開発者としての私たちの開発作業には、通常、フロントエンドとバックエンドの開発が含まれますが、テクノロジーが発展し、プロジェクトが複雑になるにつれて、フロントエンドとバックエンドの共同開発はますます重要かつ複雑になってきています。この記事では、C# 開発者が開発作業をより効率的に完了できるようにする、フロントエンドとバックエンドの共同開発テクニックをいくつか紹介します。インターフェイスの仕様を決定した後、フロントエンドとバックエンドの共同開発は API インターフェイスの相互作用から切り離せません。フロントエンドとバックエンドの共同開発をスムーズに進めるためには、適切なインターフェース仕様を定義することが最も重要です。インターフェイスの仕様にはインターフェイスの名前が含まれます

Go 言語は、高速で効率的なプログラミング言語として、バックエンド開発の分野で広く普及しています。ただし、Go 言語をフロントエンド開発と結びつける人はほとんどいません。実際、フロントエンド開発に Go 言語を使用すると、効率が向上するだけでなく、開発者に新たな視野をもたらすことができます。この記事では、フロントエンド開発に Go 言語を使用する可能性を探り、読者がこの分野をよりよく理解できるように具体的なコード例を示します。従来のフロントエンド開発では、ユーザー インターフェイスの構築に JavaScript、HTML、CSS がよく使用されます。

Golang とフロントエンド テクノロジーの組み合わせ: Golang がフロントエンド分野でどのような役割を果たしているかを調べるには、具体的なコード例が必要です。インターネットとモバイル アプリケーションの急速な発展に伴い、フロントエンド テクノロジーの重要性がますます高まっています。この分野では、強力なバックエンド プログラミング言語としての Golang も重要な役割を果たします。この記事では、Golang がどのようにフロントエンド テクノロジーと組み合わされるかを検討し、具体的なコード例を通じてフロントエンド分野での可能性を実証します。フロントエンド分野における Golang の役割は、効率的で簡潔かつ学びやすいものとしてです。
