LoginSignup
9
1

More than 1 year has passed since last update.

Node.jsのeventemitterとそのデザインパターンについてまとめてみた

Last updated at Posted at 2021-12-02

はじめに

この記事ではeventEmitterとeventEmitterに関わるデザインパターンについて紹介しています。
evenEmitterをマスターすることで、よりプロのプログラマー(略してプロプロ)になれると思います。

eventemitterとは

まずイベントエミッターとはなにか説明します。
これ、独自にイベントを作成し、指定したタイミングに関数を発火することができます
イベント駆動開発でよく用いられます。

イメージで言うと、フロントエンドでいうと、ボタンを押したときにonpushに登録された関数が発火しますよね。それです!
eventemitterを用いると、自作でイベントを作って、好きなタイミングで発火することができるようになります。
Node.jsではeventemitterがストリームの裏側で作られ、実行されています。

EventEmitterの実行例

const EventEmitter = require("events")
const eventEmitter = new EventEmitter()

const bakuhatsu=() => { console.log("ドッカーーーン") }

eventEmitter.on("爆発",bakuhatsu)
eventEmitter.once("爆発", () => {
  console.log("一回だけドッカーーーン")
})
eventEmitter.emit("爆発")
//ドッカーーーン
//一回だけドッカーーーン

eventEmitter.emit("爆発")
//ドッカーーーン

console.log("爆発解除")
eventEmitter.off("爆発",bakuhatsu)
eventEmitter.emit("爆発")
//(何もなし)

EventEmitter の主要なインスタンスメソッド

最初に簡単に用法をまとめておきます。

  1. on(イベント名、関数名)でイベントを登録し、
  2. emit(イベント名)でイベントに指定した関数を実行!
  3. off(イベント,関数名)でイベントに登録した関数の削除

on(event,listener)

指定したイベントに新しいリスナを登録します。
(第一引数に文字列 イベントの名前(任意)
 第二引数にコールバック関数 第一引数に登録したイベントが呼ばれたときに発火する)

eventEmitter.on("爆発",()=>{console.log("ドッカーーーン")})

once(event,listener)

指定したイベントに新しいリスナを登録します。
(第一引数に文字列 イベントの名前(任意)
 第二引数にコールバック関数 第一引数に登録したイベントが呼ばれたときに発火する)
これはon()メソッドと同様です。
このリスナは、イベントが一回発行されるとリスナが削除されます。なので、そのイベントの最初の一回しか第二引数に登録したコールバック関数が実行されません。

eventEmitter.once("爆発",()=>{console.log("一回だけドッカーーーン")})

off(event,listener)

on()メソッドで登録したイベントの特定のリスナを削除します。
(第一引数に文字列 イベントの名前(任意)
 第二引数にコールバック関数 on()メソッドで登録した第二引数)

eventEmitter.off("爆発",()=>{console.log("ドッカーーーン")})

emit(event,[...args])

on()やonce()メソッドで追加したイベントを発火します。
(第一引数に文字列 イベントの名前(任意)
 第二引数には引数 on()やonce()で登録したコールバック関数に引数が必要な場合のみ使用する)

eventEmitter.emit("爆発")    //今回は引数なし

使い方は、以上です

ここからは、eventemitterを利用するデザインパターンについて説明していきます。
まずかんたんにデザインパターンについて説明しておきます。

デザインパターンとは

オブジェクト指向言語で使われる設計パターンのことです。オブジェクト指向では再利用性の高いクラスが必須です。
ではどのような方向性で設計していけばよいのか。。。。
それを示してくれるのがデザインパターンです。

代表的なデザインパターンは23種類あります。(今回は詳しく説明しない)

ここではeventemitterで用いられるObserverパターンについて解説していきます。

Observerパターンについて

ObserverパターンはNode.js以外でもよく用いられる代表的なデザインパターンです。英語のObserverとは、観察者や監視役という意味があります。
このパターンでは、監視対象に対して発生した何らかのイベントが、監視役(Observer)に逐一通知されます。
監視役(Observer)はあらかじめ監視対象に対して監視を行うための登録処理を行い、監視対象はイベントの発生タイミングで登録済みの監視役(Observer)に対して通知処理を実行します。

それぞれのSubjectには複数のObserverを登録できます。

簡単な例を上げて説明します。
中学校を想定します。ここでは、一人の生徒が監視対象です。先生は一人の生徒「たかひろ」くんに対してそれぞれの処理を仕込みます。
それぞれの先生は、自分の専門の処理を「たかひろ」くんに仕込みます。
image.png

そして「たかひろ」くんは登録された処理に従って、
数学の勉強がわからないときは数学の先生に、
野球の打撃の成績が悪いときは、筋肉の先生に、(「たかひろ」くんは野球部)
熱があって、吐き気もするときは、保健室の先生に、
通知を出します。

image.png

ここまでがObserverパターンです。
先生が生徒に処理を仕込み、生徒が通知を出すところまででひとくくりです。

ここでこの例に従ってeventemitterのコードを書いてみます。

const EventEmitter = require("events")
const eventEmitter = new EventEmitter()

const helpme=(teacher)=>{
  console.log(teacher+"、助けてください")
}
eventEmitter.on("数学がわからない", helpme)
eventEmitter.on("最近打率が悪い", helpme)
eventEmitter.on("体調が悪い", helpme)

// 先生(Observer)によってイベントが仕込まれる
class takahiro {
  static suugaku_nervous() {
    eventEmitter.emit("数学がわからない","数学得意な先生")
  }
  static sports_nervous() {
    eventEmitter.emit("最近打率が悪い","筋肉ムキムキな先生")
  }
  static condition_nervous() {
    eventEmitter.emit("体調が悪い","保健室の先生")
  }
}

//「たかひろ」くんが先生にイベントを通知する
takahiro.suugaku_nervous()

//***実行結果***
//数学得意な先生、助けて!

デザインパターンとeventemitterの話はここまでです。

実際のコード

最後に実際に使われているコードの紹介をしておきます。

const http = require("http")
var fs = require("fs")
//serverのeventEmitterを作成
const server = http.createServer()

//requestというイベントに関数を仕込む
//serverにアクセスがあったときに発火する
server.on("request", (req, res) => {
  fs.readFile("./helloWorld.html", "utf-8", function (error, data) {
    res.writeHead(200, { "Content-Type": "text/html" })
    res.write("requestに登録されたイベント発火")
    res.write(data)
    res.end()
  })
})

//listeningというイベントに関数を仕込む
//これはserver.listen(8000)したときに発火する
server.on("listening", (res, req) => {})

//errorというイベントに関数を仕込む
//エラーが起こったときに発火する
server.on("error", err =>{
  console.error(err);
})

//closeというイベントに関数を仕込む
//これはserver.close()したときに発火する(ここではserver.close()はこめんとあうとした)
server.on("close", () => {})

server.listen(8000)
// server.close()
helloEarth.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>Hello,Earth! And,Hello universe!</h1>
</body>
</html>

localhost:8000にアクセスした結果

image.png

何気なくhttpモジュールで使っていた関数にもeventEmitterが仕込まれていました。自分が使っている関数や処理がeventEmitterのものかどうか見極める事ができれば、プログラミングのレベルもぐんぐん上がっていくと思いますl

最後に

Streamの記事を書くつもりがいつマニカeventEmitter の記事を書いていました。
次回はStreamの記事を書きます!!

おいらの記事を最後まで見てくれてありがとうございました。

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1