Event emitters
| Subscribe | |
| Publish | |
| Unsubscribe | |
| Typed event maps |
Subscribe
An emitter keeps a list of listener functions and calls each one when something happens. The on function adds a listener, and the rest of the program stays unaware of who listens.
Type the listener once, for example as a function that takes a string message and returns void. Every subscriber then matches the same shape, and the compiler rejects mismatched handlers.
type Listener = (msg: string) => void;
const listeners: Array<Listener> = [];
function on(listener: Listener): void {
listeners.push(listener);
}
on(function show(msg: string): void {
console.log(msg);
});
Publish
Publishing means looping over the list and calling every listener with the same event data. Emitters never return results from listeners, they only notify.
Keep emit synchronous for simple cases so the order of listeners matches the order of subscription. Async delivery can come later, once the basic flow is solid.
// same list as above
function emit(msg: string): void {
for (const next of listeners) {
next(msg);
}
}
emit("hello");
Unsubscribe
Listeners that are never removed keep their closures alive for the life of the emitter. An off function finds the listener and splices it out of the array.
Always unsubscribe when a component is destroyed or a task finishes. Short lived subscribers on a long lived emitter are the classic source of slow memory growth.
// same list as above
function off(listener: Listener): void {
const at: number = listeners.indexOf(listener);
if (at !== -1) {
listeners.splice(at, 1);
}
}
Typed event maps
Real programs carry different payloads per event, so one string type is not enough. An event map type lists each event name next to its payload type, and a generic publish checks the pair.
The compiler then rejects a publish call with the wrong payload for the name. Renaming an event breaks at compile time instead of failing silently at runtime.
type Events = {
start: string;
stop: number;
};
function publish<K extends keyof Events>(name: K, data: Events[K]): void {
console.log(name);
console.log(data);
}
publish("start", "ready");
Next: Streams
Article author: Arthur Isaev