Skip to main content
File

title: createEventHub tags: browser,event,advanced

TS JS Deno

Creates a pub/sub (publish–subscribe) event hub with emit, on, and off methods.

Use Object.create(null) to create an empty hub object that does not inherit properties from Object.prototype. For emit, resolve the array of handlers based on the event argument and then run each one with Array.prototype.forEach() by passing in the data as an argument. For on, create an array for the event if it does not yet exist, then use Array.prototype.push() to add the handler to the array. For off, use Array.prototype.findIndex() to find the index of the handler in the event array and remove it using Array.prototype.splice().

const createEventHub = <T = any>() => ({
  hub: Object.create(null),
  emit(event: string, data?: T) {
    (this.hub[event] || []).forEach((handler: Func<T | undefined>) =>
      handler(data)
    );
  },
  on(event: string, handler: Func<T>) {
    if (!this.hub[event]) this.hub[event] = [];
    this.hub[event].push(handler);
  },
  off(event: string, handler: Func<T>) {
    const i = (this.hub[event] || []).findIndex((h: Func<T>) => h === handler);
    if (i > -1) this.hub[event].splice(i, 1);
    if (this.hub[event]?.length === 0) delete this.hub[event];
  },
});

Basic String emitter:

const handler = (data: string) => console.log(data);
const hub = createEventHub<string>();

// Subscribe: listen for different types of events
hub.on("message", handler);
hub.on("message", () => console.log("Message event fired"));

// Publish: emit events to invoke all handlers subscribed to them, passing the data to them as an argument
hub.emit("message", "hello world"); // logs 'hello world' and 'Message event fired'

// Unsubscribe: stop a specific handler from listening to the 'message' event
hub.off("message", handler);
hub.emit("message", "hello world");

Number Incremental:

let increment = 0;
const numEmitter = createEventHub<number>();
const incrementHandler = () => increment++;
numEmitter.on("increment", incrementHandler);
numEmitter.emit("increment"); // `increment` variable is now 1
numEmitter.emit("increment"); // `increment` variable is now 1
numEmitter.off("increment", incrementHandler);
numEmitter.emit("increment"); // `increment` variable is now 1
assertEquals(increment, 2);

User Emitter:

interface User {
  name: string;
}
let user: User | undefined;
const userEmitter = createEventHub<User>();
const updateUser = (u: User) => (user = u);
userEmitter.on("update", updateUser);
userEmitter.emit("update", { name: "Deepak" });

assertEquals(user, { name: "Deepak" });