Hone logo
Hone
Problems

Simple Event Emitter in JavaScript

Event emitters are a fundamental pattern in many programming languages, allowing objects to notify multiple listeners when a specific event occurs. This challenge asks you to implement a basic event emitter in JavaScript, enabling you to understand the core principles behind this powerful design pattern. Building this will give you a solid foundation for working with libraries and frameworks that utilize event-driven architectures.

Problem Description

You are tasked with creating a JavaScript class called EventEmitter. This class should allow users to:

  1. Subscribe to events: A user should be able to register a callback function to be executed when a specific event is emitted. This registration should be done using a method called on(eventName, callback).
  2. Emit events: A user should be able to trigger an event, which will then execute all registered callbacks for that event. This should be done using a method called emit(eventName, ...args). The ...args should be passed as arguments to the callbacks.
  3. Remove subscriptions: A user should be able to remove a previously registered callback function using a method called off(eventName, callback). This should only remove the exact callback function provided, not all callbacks for that event name.
  4. Handle multiple listeners: The emitter should support multiple callbacks registered for the same event. All registered callbacks should be executed when the event is emitted.

Expected Behavior:

  • on(eventName, callback): Registers callback to be executed when eventName is emitted.
  • emit(eventName, ...args): Executes all registered callbacks for eventName, passing ...args as arguments.
  • off(eventName, callback): Removes callback from the list of listeners for eventName. If the callback is not found, the function should do nothing.
  • If an event is emitted and no listeners are registered for that event, the function should do nothing.

Edge Cases to Consider:

  • What happens if on is called with invalid arguments (e.g., eventName is not a string, callback is not a function)? (For simplicity, you can ignore argument validation in this challenge.)
  • What happens if emit is called with an event name that has no listeners?
  • What happens if off is called with an event name that has no listeners, or with a callback that was never registered?
  • What happens if off is called with an invalid callback (e.g., not a function)? (For simplicity, you can ignore argument validation in this challenge.)

Examples

Example 1:

Input:
let emitter = new EventEmitter();
emitter.on('data', (x) => console.log(x));
emitter.emit('data', 1);
emitter.emit('data', 2);

Output:
1
2
Explanation:
The 'data' event is emitted twice, and the callback function logs the provided argument to the console each time.

Example 2:

Input:
let emitter = new EventEmitter();
let callback1 = (x) => console.log(x);
let callback2 = (x) => console.log(x * 2);
emitter.on('data', callback1);
emitter.on('data', callback2);
emitter.emit('data', 5);
emitter.off('data', callback1);
emitter.emit('data', 10);

Output:
10
20
Explanation:
Initially, both callbacks are registered for the 'data' event. The first emit executes both, logging 5 and 10.  `callback1` is then removed. The second emit only executes `callback2`, logging 20.

Example 3: (Edge Case)

Input:
let emitter = new EventEmitter();
emitter.emit('nonExistentEvent');

Output:
(No output)
Explanation:
The 'nonExistentEvent' event is emitted, but there are no listeners registered for it, so nothing happens.

Constraints

  • The EventEmitter class should be implemented using JavaScript.
  • The on, emit, and off methods must be implemented as described above.
  • The code should be reasonably efficient. While performance is not the primary focus, avoid unnecessary complexity.
  • The class should be well-structured and easy to understand.

Notes

  • Consider using a data structure (e.g., an object or a map) to store the event listeners.
  • The off method requires careful comparison of callback functions to ensure that only the exact callback is removed. JavaScript's strict equality (===) is recommended for this comparison.
  • This is a simplified event emitter. Real-world event emitters often include features like error handling, event prioritization, and more sophisticated listener management. Focus on the core functionality for this challenge.
Loading editor...
javascript