Implement Event Emitter
An Event Emitter is a design pattern that allows objects to emit named events and register listeners for those events. This is fundamental to understanding how many JavaScript libraries and frameworks work.
Problem Statement
Implement a custom EventEmitter class with the following methods:
on(event, listener)
- Register a listener for an eventoff(event, listener)
- Remove a listener for an eventemit(event, ...args)
- Emit an event with optional argumentsonce(event, listener)
- Register a one-time listener
Solution
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
}
off(event, listener) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(
l => l !== listener
);
}
emit(event, ...args) {
if (!this.events[event]) return;
this.events[event].forEach(listener => {
listener(...args);
});
}
once(event, listener) {
const onceWrapper = (...args) => {
listener(...args);
this.off(event, onceWrapper);
};
this.on(event, onceWrapper);
}
}
Usage Example
const emitter = new EventEmitter();
// Register listeners
emitter.on('data', (data) => {
console.log('Received data:', data);
});
emitter.on('error', (error) => {
console.error('Error occurred:', error);
});
// Emit events
emitter.emit('data', { message: 'Hello World' });
emitter.emit('error', new Error('Something went wrong'));
// One-time listener
emitter.once('ready', () => {
console.log('System is ready!');
});
emitter.emit('ready'); // Will log and remove the listener
emitter.emit('ready'); // Nothing happens
Key Concepts
- Event Registration: Store listeners in an object with event names as keys
- Listener Management: Use arrays to store multiple listeners per event
- Event Emission: Iterate through listeners and call them with arguments
- One-time Listeners: Wrap the original listener to auto-remove after execution
Common Interview Questions
- How would you handle memory leaks with event listeners?
- What's the difference between
on
andonce
? - How would you implement event namespacing?
- How would you add support for async listeners?
Related Topics
- Observer Pattern
- Pub/Sub Pattern
- Node.js EventEmitter
- React Event System