---
# System prepended metadata

title: Technical Mock Interview

---

# Technical Mock Interview

## Overview

One of the most important concepts in JavaScript is the idea of Events. The Event Emitter pattern is central to web development.

### Question 

#### Create an Event Emitter Class from Scratch with the Following Methods (30 mins)

**You are only allowed to use the [Nodejs Documentation](https://nodejs.org/api/events.html#events_events) and the [MDN Documentation](https://developer.mozilla.org/en-US/)**

**addListener(eventName, handlerToBeAdded)**

- Be able to add listeners to an object/Register an event
- eventName is the name of the event being listened to
- handlerToBeAdded is the event handler function
- https://nodejs.org/api/events.html#events_event_newlistener

**on(eventName, handlerToBeAdded)**

- An alias for addListener
- https://nodejs.org/api/events.html#events_emitter_on_eventname_listener

**removeListener(eventName, handlerToBeRemoved)**

- Be able to remove listeners from the object
- eventName is the name of the event we are trying to remove
- handlerToBeRemoved is event handler function
- https://nodejs.org/api/events.html#events_event_removelistener

**off(eventName, handlerToBeRemoved)**

- Alias for removeListener
- https://nodejs.org/api/events.html#events_emitter_off_eventname_listener

**emit(eventName, ...eventData)**

- eventName is the name of the event
- ...eventDate is the list of arguments being supplied
- Synchronously calls each of the events registered to eventName
- https://nodejs.org/api/events.html#events_emitter_emit_eventname_args

**getListeners(eventName)**

- Return the listeners registered to the event name
- https://nodejs.org/api/events.html#events_emitter_rawlisteners_eventname

**getListenersLength(eventName)**

- Return the length of the array of listeners registered to the event name
- https://nodejs.org/api/events.html#events_emitter_listenercount_eventname

**[Extra Credit] once(eventName, handlerToAddThenRemove)**

- Be able to add a one time listener to our object, and when we emit it, it's immediately removed
- eventName is the name of the event
- handlerToAddThenRemove is the event handler funciton
- https://nodejs.org/api/events.html#events_emitter_once_eventname_listener

Demo of EventEmitter Class in Node:

```javascript

/*
  Event emitters are a common pattern for "registering" (storing) functions to be executed at a later time in response to some sort of arbitrary "event".

*/
// Example usage of the in built Event Emitter
const EventEmitter = require('events')

// Create new EventEmitter
const ee = new EventEmitter()

// Register an event with the name 'event'
ee.on('event', () => {
console.log('an event occurred!');
})

// "Call" the event with the name 'event' executing everything attached to it synchronously
ee.emit('event')
```

#### Solution

```javascript
class CoolerEventEmitter {
    constructor(listeners = {}) {
      this.listeners = listeners
    }

    /*
    * addListener(eventName, cb)
    * 1. Check if eventName exists already in our listener object
    * 2. If yes, return that array
    * 3. If no, return an empty array
    * 4. Push cb into our array 
    */

    addListener(eventName, cb) {
        this.listeners[eventName] = this.listeners[eventName] || []
        return this.listeners[eventName].push(cb)
    }

    /*
    * on(eventName, cb): Alias for addListener
    */

    on(eventName, cb) {
        return this.addListener(eventName, cb)
    }

    /*
    * removeListener(eventName, cb)
    * 1. Make sure that eventName exists; if not, return false
    * 2. If it does, splice that array at the index of the cb
    */

    removeListener(eventName, cb) {
        let temp = this.listeners[eventName]

        if(!temp) return false

        return temp.splice(temp.indexOf(cb), 1)

    }

    /*
    * off(eventName, cb): Alias for removeListener
    */

    off(eventName, cb) {
        return this.removeListener(eventName, cb)
    }

    /*
    * emit(eventName, ...args)
    * 1. Make sure eventName exists; if not, return false
    * 2. Call the arguments on every element of the array
    */

    emit(eventName, ...args) {
        let temp = this.listeners[eventName]

        if (!temp) return false

        return temp.forEach((f) => {
            f(...args)
        })
    }

    /*
    * once(eventName, cb)
    * 1. Same idea as addListener/on: Check if eventName exists in the object
    * 2. If yes, return that array
    * 3. If no, return empty array
    * 4. Define a wrapper function and it will fire the cb as well as remove the listener
    * 5. Push the wrapper function into the array
    */

    once(eventName, cb) {
        this.listeners[eventName] = this.listeners[eventName] || []

        const wrapper = () => {
            cb()
            return this.off(eventName, wrapper)
        }

        return this.listeners[eventName].push(wrapper)

    }

    /*
    * getListeners(eventName)
    */

    getListeners(eventName) {
        return this.listeners[eventName]
    }

    /*
    * getListenerLength(eventName)
    */

    getListenerLength(eventName) {
        let temp = this.listeners[eventName]
        return temp.length
    }

}
```

### [Replit](https://repl.it/join/vatmzgqf-b17z)
