Event Emitter

class EventEmitter {
  constructor() {
    this.listeners = {};
  }

  subscribe(event, callback) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
    return this;
  }

  unsubscribe(event, callback) {
    if (!this.listeners[event]) {
      throw new Error("Failed to unsubscribe: " + event + " not exist.");
    }
    this.listeners[event] = this.listeners[event].filter((cb, index) => {
      return cb != callback;
    });
    return this;
  }

  subscribeOnce(event, callback) {
    let onceCallbackWrapper = (...args) => {
      callback.apply(this, args);
      this.unsubscribe(event, onceCallbackWrapper);
    };

    this.subscribe(event, onceCallbackWrapper);
    return this;
  }

  listenerCount(event) {
    return this.listeners[event].length;
  }

  rawListeners(event) {
    return this.listeners[event];
  }

  emit(event, ...args) {
    if (!this.listeners[event]) {
      throw new Error("Failed to emit: " + event + " not exist.");
    }
    this.listeners[event].forEach((cb) => {
      cb.apply(this, args);
    });
    return this;
  }
}
const eventEmitter = new EventEmitter();

eventEmitter.subscribe("event1", (data) => {
  console.log("Event1 emitted with data:", data);
});
eventEmitter.emit("event1", [400, 200]);

const callbackToUnsubscribe = (data) => {
  console.log("Callback to unsubscribe, data:", data);
};
eventEmitter.subscribe("event2", callbackToUnsubscribe);
eventEmitter.emit("event2", "Test data");
eventEmitter.unsubscribe("event2", callbackToUnsubscribe);
eventEmitter.emit("event2", "Test data after unsubscribe");

eventEmitter.subscribeOnce("event3", () => {
  console.log("Event3 emitted. This should only be printed once.");
});
eventEmitter.emit("event3");
eventEmitter.emit("event3");

eventEmitter.subscribe("event4", () => {
  console.log("callback 1");
});
eventEmitter.subscribe("event4", () => {
  console.log("callback 1");
});
console.log("Listener count of event4:", eventEmitter.listenerCount("event4"));
console.log("Raw listeners of event4:", eventEmitter.rawListeners("event4"));

try {
  eventEmitter.emit("nonexistentEvent");
} catch (error) {
  console.log("Error:", error.message);
}

try {
  eventEmitter.unsubscribe("nonexistentEvent", () => {});
} catch (error) {
  console.log("Error:", error.message);
}

// Event1 emitted with data: [ 400, 200 ]

// Callback to unsubscribe, data: Test data

// Event3 emitted. This should only be printed once.

// Listener count of event4: 2

// Raw listeners of event4: [ [Function (anonymous)], [Function (anonymous)] ]

// Error: Failed to emit: nonexistentEvent not exist.

// Error: Failed to unsubscribe: nonexistentEvent not exist.