Skip to main content

Overview

The EventEmitter class provides a robust, type-safe event system for implementing pub/sub patterns in your application. It supports synchronous and asynchronous event handlers, one-time listeners, error handling, and listener limits.

Import

import { EventEmitter, createEventEmitter } from 'bytekit';

Usage

Basic Event Emitter

// Define event types
interface Events {
  userLoggedIn: { userId: string; timestamp: number };
  dataUpdated: { id: string; data: any };
  error: Error;
}

// Create event emitter
const emitter = new EventEmitter<Events>();

// Register listener
emitter.on('userLoggedIn', (data) => {
  console.log(`User ${data.userId} logged in at ${data.timestamp}`);
});

// Emit event
await emitter.emit('userLoggedIn', {
  userId: '123',
  timestamp: Date.now()
});

One-time Listeners

// Register one-time listener
emitter.once('dataUpdated', (data) => {
  console.log('Data updated:', data);
  // This handler will be automatically removed after first execution
});

emitter.emit('dataUpdated', { id: '1', data: { value: 100 } });
emitter.emit('dataUpdated', { id: '2', data: { value: 200 } }); // Won't trigger

Error Handling

const emitter = new EventEmitter({
  captureRejections: true // Capture and handle errors
});

// Register error handler
emitter.onError((data, error) => {
  console.error('Event handler error:', error);
  console.log('Event data:', data);
});

emitter.on('dataUpdated', async (data) => {
  throw new Error('Handler failed');
  // Error will be caught and passed to error handlers
});

Factory Function

const emitter = createEventEmitter<Events>({
  maxListeners: 20,
  captureRejections: true
});

API Reference

Constructor

options
EventEmitterOptions
default:"{}"
Configuration options for the event emitter

Methods

on

Register an event listener.
event
keyof Events
required
Event name to listen for
listener
EventListener<Events[K]>
required
Callback function to execute when event is emitted
return
this
Returns the emitter instance for method chaining
emitter.on('userLoggedIn', (data) => {
  console.log(data.userId);
});

once

Register a one-time event listener that will be automatically removed after first execution.
event
keyof Events
required
Event name to listen for
listener
EventListener<Events[K]>
required
Callback function to execute once
return
this
Returns the emitter instance for method chaining

off

Remove an event listener.
event
keyof Events
required
Event name
listener
EventListener<Events[K]>
required
The listener function to remove
return
this
Returns the emitter instance for method chaining
const handler = (data) => console.log(data);
emitter.on('dataUpdated', handler);
emitter.off('dataUpdated', handler);

emit

Emit an event asynchronously, waiting for all async handlers to complete.
event
keyof Events
required
Event name to emit
data
Events[K]
required
Data to pass to event listeners
return
Promise<boolean>
Promise resolving to true if event had listeners, false otherwise
const hasListeners = await emitter.emit('dataUpdated', { id: '1', data: {} });

emitSync

Emit an event synchronously without waiting for async handlers.
event
keyof Events
required
Event name to emit
data
Events[K]
required
Data to pass to event listeners
return
boolean
Returns true if event had listeners, false otherwise
const hasListeners = emitter.emitSync('dataUpdated', { id: '1', data: {} });

removeAllListeners

Remove all listeners for an event, or all listeners if no event specified.
event
keyof Events
Event name (optional - if omitted, removes all listeners for all events)
return
this
Returns the emitter instance for method chaining
emitter.removeAllListeners('dataUpdated'); // Remove listeners for specific event
emitter.removeAllListeners(); // Remove all listeners

onError

Register an error handler for capturing errors from event listeners.
listener
EventListenerWithError
required
Error handler callback receiving (data, error)
return
this
Returns the emitter instance for method chaining

listenerCount

Get the number of listeners for an event.
event
keyof Events
required
Event name
return
number
Number of listeners registered for the event
const count = emitter.listenerCount('dataUpdated');

getListeners

Get all listeners for an event.
event
keyof Events
required
Event name
return
EventListener<Events[K]>[]
Array of listener functions

eventNames

Get all event names that have listeners.
return
(keyof Events)[]
Array of event names
const events = emitter.eventNames(); // ['userLoggedIn', 'dataUpdated']

setMaxListeners

Set the maximum number of listeners per event.
n
number
required
Maximum number of listeners
return
this
Returns the emitter instance for method chaining

getMaxListeners

Get the maximum number of listeners per event.
return
number
Maximum listener count

Types

EventListener

type EventListener<T = unknown> = (data: T) => void | Promise<void>;
Event listener function that can be sync or async.

EventListenerWithError

type EventListenerWithError<T = unknown> = (
  data: T,
  error?: Error
) => void | Promise<void>;
Error handler function receiving event data and error.

EventEmitterOptions

interface EventEmitterOptions {
  maxListeners?: number;
  captureRejections?: boolean;
}

Best Practices

Type Safety

Always define event types for type-safe event handling:
interface AppEvents {
  'user:login': { userId: string };
  'user:logout': { userId: string };
  'data:update': { id: string; data: any };
}

const emitter = new EventEmitter<AppEvents>();

Memory Management

Remember to remove listeners when they’re no longer needed:
const dispose = () => {
  emitter.off('dataUpdated', handler);
};

// Or remove all listeners
const cleanup = () => {
  emitter.removeAllListeners();
};

Error Handling

Enable error capture for production applications:
const emitter = new EventEmitter({
  captureRejections: true
});

emitter.onError((data, error) => {
  logger.error('Event handler error', { error, data });
});