newListeners

The newListeners function provides a simple utility to manage event listeners, allowing you to register listeners and notify them asynchronously while handling errors gracefully.

Implementation
function newListeners<T extends unknown[], E = unknown>(
  onError: (error: E) => void = console.error,
): [
  addListener: (listener: (...args: T) => void | Promise<void>) => () => void,
  notifyListeners: (...args: T) => Promise<void>,
] {
  const listeners: {
    [listenerId: number]: (...args: T) => void | Promise<void>;
  } = {};
  let listenerId = 0;
  function addListener(
    listener: (...args: T) => void | Promise<void>,
  ): () => void {
    const id = listenerId++;
    listeners[id] = listener;
    return () => {
      delete listeners[id];
    };
  }
  async function notify(...args: T): Promise<void> {
    for (const listener of Object.values(listeners)) {
      try {
        await listener(...args);
      } catch (e) {
        onError(e as E);
      }
    }
  }
  return [addListener, notify];
}

Examples

const [addListener, notifyListeners] = newListeners<[string]>();

const removeListener = addListener((message) => {
  console.log(`Received message: ${message}`);
});

notifyListeners("Hello, World!");
// Output: Received message: Hello, World!

removeListener();
notifyListeners("This won't be logged.");

Advanced Example with Error Handling:

const [addListener, notifyListeners] = newListeners<[string], Error>((error) => {
  console.error("Listener failed:", error.message);
});

addListener(async (message) => {
  console.log(`Processing: ${message}`);
  if (message === "error") {
    throw new Error("Intentional error.");
  }
  await new Promise((resolve) => setTimeout(resolve, 1000));
  console.log(`Processed: ${message}`);
});

await notifyListeners("test");
// Output: 
// Processing: test
// Processed: test

await notifyListeners("error");
// Output: 
// Processing: error
// Listener failed: Intentional error.

Signature

Parameters:

Returns a tuple containing two functions:

  1. addListener : (listener: (...args: T) => void | Promise<void>) => () => void: Registers a new listener and returns a function to remove the listener.
  2. notifyListeners: (...args: T) => Promise<void>: Asynchronously invokes all registered listeners with the provided arguments.

Behavior Details

Use Cases

This function is useful for applications that involve asynchronous events or require custom error handling for event listeners:

See Also