Node.js - The EventEmitter
Tags: node, javascript, eventdriven
Published: 2020-11-28 09:39:16

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0w9ues4l9z6ssozw55u5.jpeg)


#### Overview
This article is **Part 1** of [Working With Node.js](https://dev.to/meddy672/series/20844) , a series of articles to help simplify learning Node.js. The topic which I will focus on here will be [Node.js EventEmitter](https://nodejs.org/dist/latest-v15.x/docs/api/events.html#events_events).

#### Objectives
In this article, we will learn what the Node.js EventEmitter is, and how we can use it. We will start with an introduction, then show some code examples. Finally, we'll learn some fundamental concepts about event emitters and use those concepts to build our own *SimpleEmitter* with just plain JavaScript.

#### Section 1 - About The Event Emitter
In its simplest form, the event emitter in Node.js is just a **Callback**. To be precise its an array of callbacks. What do we use event emitters for? We actually use them quite often. HTTP *server*, *response* and *request* objects all inherit the event emitter class. Event emitters allow us to incorporate an event driven design pattern on our server or application. This design pattern works very similar to a publisher and subscriber pattern, where the event emitter will publish new messages to all its listeners, and the listeners will respond and react to its caller.


#### Section 2 - Working With Node.js Event Emitter
Creating an event emitter with Node.js is pretty straight forward. The event emitter is a class within the [events](https://nodejs.org/dist/latest-v15.x/docs/api/events.html#events_events) module, therefore  it must be required.

##### index.js
```javascript
   const { EventEmitter } = require('events');

   const simpleEmitter = new EventEmitter();
```
Once we have the emitter imported, we can create a listener and publish messages to the listener. To add listeners we use the **`on`** method of the event emitter followed by the name of the event. You can name your events whatever like as it is only used to identify what listeners will execute when a message is published or sent. I have named my listener **my-simple-event**.

##### index.js
```javascript
const { EventEmitter } = require('events');

const simpleEmitter = new EventEmitter();

simpleEmitter.on('my-simple-event', () => {
    console.log('Running Simple Event Callback...');
});

```
As you can see the **`on`** method takes the name of the event to listen to, and a function to run once we send a message to it. Now, we just need to publish a message to that event. We can do that with the **`emit`** method followed by the name of the event. Putting it all together
##### index.js
```javascript
const { EventEmitter } = require('events');

const simpleEmitter = new EventEmitter();

simpleEmitter.on('my-simple-event', () => {
    console.log('Running Simple Event Callback...');
});
simpleEmitter.emit('my-simple-event');
```
##### Output
```
Running Simple Event Callback...
```

Once a message is published with the **`emit`** method, the listener will run the callback function. In its simplest form, this is the Node.js event emitter in action. You can create as many events as you like for as many listeners as you need. You also can supply arguments to the callback function of the listener by passing additional arguments to the **`emit`** method. Lets do that now. I'll create another listener called **another-simple-event** and I'll pass an object to it using the **`emit`** method.

##### index.js
```javascript
const { EventEmitter } = require('events');

const simpleEmitter = new EventEmitter();

const user = { id: 1, name: 'John Doe'}

simpleEmitter.on('my-simple-event', () => {
    console.log('Running Simple Event Callback...');
});

simpleEmitter.on('another-simple-event', (user) => {
    console.log('Doing work on', user);
});
simpleEmitter.emit('my-simple-event');
simpleEmitter.emit('another-simple-event', user);
``` 

##### Output
```
 Running Simple Event Callback...
 Doing work on  { id: 1, name: 'John Doe' } 
```

The event emitter class within Node.js has a ton of built-in methods that you can use right out of the box. Below are some commonly used methods.
* [on](https://nodejs.dev/learn/the-nodejs-events-module) - will register a listener for that event.
* [emit](https://nodejs.dev/learn/the-nodejs-events-module) - will publish or send new messages to it's listeners.
* [once](https://nodejs.dev/learn/the-nodejs-events-module) - will run only once and discontinue listening to further messages.
* [off](https://nodejs.dev/learn/the-nodejs-events-module) - removes all listeners from an event.


Now, no code is complete without some error handling. If an error occurs while an event is being published then the process will **crash**. To avoid this you can register an <strong>error</strong> listener to handle errors. Lets do that now. I'll add a third listener called error which will be used to handle errors for the `simpleEmitter`. I'll emit the error before I publish a message to the <i>another-simple-event</i> listener.

##### index.js
```javascript
const { EventEmitter } = require('events');

const simpleEmitter = new EventEmitter();

const user = { id: 1, name: 'John Doe'}

simpleEmitter.on('my-simple-event', () => {
    console.log('Running Simple Event Callback...');
});

simpleEmitter.on('another-simple-event', (user) => {
    console.log('Doing work on', user);
});

simpleEmitter.on('error', (err) => {
    console.error('I received the error ',err.message);
});
simpleEmitter.emit('my-simple-event');
simpleEmitter.emit('error', new Error('oh oh'));
simpleEmitter.emit('another-simple-event', user);
```
##### Output
```
Running Simple Event Callback...
I received the error  oh oh
Doing work on  { id: 1, name: 'John Doe' }
```
If you remove the **error listener** and run the program again the process will crash and *another-simple-event* will not publish a message to its listener.

#### Section 3 - Building An Event Emitter With Just JavaScript
As I stated before, the event emitter is just an **array of callbacks**. Let me show you what I mean with the code snippet below.
##### Code snippet
```javascript
const mySimpleEvent = [
    function () { console.log('Hello') },
    function (user) { console.log(user) },
    function () { console.log('World') }
];
mySimpleEvent.forEach((fn, index) => {
    if (index === 1) {
        const user = { id: 1, name: 'John Doe' }
        fn(user);
    } else {
        fn();
    }
});
```
In the code snippet above, I created an array that contains three functions where each function will do something different. Next, I loop through the array calling each function and for the second index of the array, I pass in a user object. If you run the code above you will receive the output below.
##### Output
```
Hello
{ id: 1, name: 'John Doe' }
World
```
From the code snippet above, we can derive some simple fundamental concepts about the event emitter and thus event driven development. If we have an application that is defined by a set of use cases or events, then we can design our application to work based on those events. Now, in regards to the `mySimpleEvent` from the code snippet above, each function represents a listener that is attached to `mySimpleEvent`. From there, all we have to do is loop through `mySimpleEvent` and call each listener. With this knowledge we can build are own event emitter class, lets do that now. I'll create another file called *SimpleEmitter.js*. This class will have two methods **`on`** and **`emit`** just like the those of Node.js's event emitter class.

##### SimpleEmitter.js
```javascript

class SimpleEmitter {
    constructor() {
        this.event = {};
    }
    on(eventName, listener) {
        if (!this.event[eventName]) {
            this.event[eventName] = [];
        }
        return this.event[eventName].push(listener);
    }
    emit(eventName, data) {
        if (!this.event[eventName]) {
            return;
        }
        this.event[eventName].forEach((cb) => {
            cb(data);
        });
    }
}
```
Lets take a moment to understand the SimpleEmitter class. Each time we call the **`on`** method we check to see if the event name is stored within our event object. If the event name is not found, we create a **key** for it to reference an array of listeners. Once the **`emit`** method is called, it will check for the event name and if not found the method will end there. If it does find the event name then it will loop through the array and call each listener. Now we just need to use the SimpleEmitter class as we did before. Putting it all together

##### SimpleEmitter.js
```javascript

class SimpleEmitter {
    constructor() {
        this.event = {};
    }
    on(eventName, listener) {
        if (!this.event[eventName]) {
            this.event[eventName] = [];
        }
        return this.event[eventName].push(listener);
    }
    emit(eventName, data) {
        if (!this.event[eventName]) {
            return;
        }
        this.event[eventName].forEach((cb) => {
            cb(data);
        });
    }
}

const myEmitter = new SimpleEmitter();
const user = { id: 1, name: 'John Doe' };

myEmitter.on('my-simple-event', () => {
    console.log('Running Simple Event Callback');
});

myEmitter.on('another-simple-event', (user) => {
    console.log('Doing work on', user);
});
myEmitter.on('error', (err) => {
    console.log('I received the error',err.message);
})
myEmitter.emit('my-simple-event');
myEmitter.emit('another-simple-event', user);
myEmitter.emit('error', new Error('oh oh'));
```

##### Output
```
Running Simple Event Callback
I received the error oh oh
Doing work on { id: 1, name: 'John Doe' }
```
The EventEmitter class within Node.js covers more complex use cases within its application code. However, the fundamentals are the same. Thank you for taking time to read this article and if you found it helpful please leave a rating. If you have a question please post it in the discussion below.