JavaScriptmediumJavaScript

Simple Event Emitter

Lightweight event emitter pattern implementation

01

The problem

Need event-driven communication between components

02

The solution

JavaScript
class EventEmitter {
  constructor() {
    this.events = {};
  }
  
  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(listener);
    return this;
  }
  
  off(event, listener) {
    if (!this.events[event]) return this;
    
    if (listener) {
      this.events[event] = this.events[event].filter(l => l !== listener);
    } else {
      delete this.events[event];
    }
    
    return this;
  }
  
  emit(event, ...args) {
    if (!this.events[event]) return false;
    
    const listeners = this.events[event].slice();
    listeners.forEach(listener => {
      try {
        listener.apply(this, args);
      } catch (error) {
        console.error(`Error in event listener for "${event}":`, error);
      }
    });
    
    return true;
  }
  
  once(event, listener) {
    const onceListener = (...args) => {
      this.off(event, onceListener);
      listener.apply(this, args);
    };
    return this.on(event, onceListener);
  }
  
  listeners(event) {
    return this.events[event] ? this.events[event].slice() : [];
  }
  
  removeAllListeners() {
    this.events = {};
    return this;
  }
}

03

Put it to work

Example
const emitter = new EventEmitter();

// Subscribe to events
emitter.on('userLogin', (user) => {
  console.log(`User logged in: ${user.name}`);
});

emitter.on('userLogin', (user) => {
  console.log(`Sending welcome email to: ${user.email}`);
});

// One-time listener
emitter.once('firstLogin', (user) => {
  console.log(`First login for: ${user.name}`);
});

// Emit events
emitter.emit('userLogin', { name: 'John', email: '[email protected]' });
// "User logged in: John"
// "Sending welcome email to: [email protected]"

emitter.emit('firstLogin', { name: 'Jane' });
// "First login for: Jane"

emitter.emit('firstLogin', { name: 'Bob' });
// (Nothing happens - one-time listener already removed)

// Remove specific listener
const listener = (data) => console.log('Listener:', data);
emitter.on('test', listener);
emitter.off('test', listener);