or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

EventEmitter3

EventEmitter3 is a high-performance EventEmitter that provides a drop-in replacement for Node.js's built-in EventEmitter with significant performance improvements. It maintains API compatibility while offering contextual event emission and optimized code paths for high-frequency event handling.

Package Information

  • Package Name: eventemitter3
  • Package Type: npm
  • Language: JavaScript (with TypeScript definitions)
  • Installation: npm install eventemitter3

Core Imports

const EventEmitter = require('eventemitter3');

ESM:

import EventEmitter from 'eventemitter3';
// or
import { EventEmitter } from 'eventemitter3';

TypeScript:

import EventEmitter from 'eventemitter3';
// With custom event types
import EventEmitter from 'eventemitter3';

interface MyEvents {
  'data': [string, number];
  'error': [Error];
  'close': [];
}

const emitter = new EventEmitter<MyEvents>();

Basic Usage

const EventEmitter = require('eventemitter3');
const emitter = new EventEmitter();

// Add event listeners
emitter.on('data', (message) => {
  console.log('Received:', message);
});

// Add one-time listener
emitter.once('ready', () => {
  console.log('System ready!');
});

// Emit events
emitter.emit('data', 'Hello World');
emitter.emit('ready');

// Remove listeners
emitter.removeListener('data');
emitter.removeAllListeners();

Key Differences from Node.js EventEmitter

  • Contextual emission: Optional context parameter for listeners (eliminates fn.bind)
  • Performance optimized: Micro-optimized for high-frequency event handling
  • Removed features: No domain support, no error event throwing, no newListener/removeListener events
  • Different behavior: removeListener removes ALL matching listeners, not just the first

Capabilities

EventEmitter Constructor

Creates a new EventEmitter instance.

/**
 * Creates a new EventEmitter instance
 */
function EventEmitter();

// TypeScript generic version
class EventEmitter<EventTypes = string | symbol, Context = any> {
  constructor();
}

Event Listener Management

Add, remove, and query event listeners with optional context support.

/**
 * Add a listener for a given event
 * @param {string|symbol} event - The event name
 * @param {Function} fn - The listener function
 * @param {*} [context] - The context to invoke the listener with
 * @returns {EventEmitter} this - For method chaining
 */
on(event, fn, context);

/**
 * Add a one-time listener for a given event
 * @param {string|symbol} event - The event name
 * @param {Function} fn - The listener function
 * @param {*} [context] - The context to invoke the listener with
 * @returns {EventEmitter} this - For method chaining
 */
once(event, fn, context);

/**
 * Remove the listeners of a given event
 * Note: Removes ALL matching listeners, not just the first
 * @param {string|symbol} event - The event name
 * @param {Function} [fn] - Only remove listeners that match this function
 * @param {*} [context] - Only remove listeners that have this context
 * @param {boolean} [once] - Only remove one-time listeners
 * @returns {EventEmitter} this - For method chaining
 */
removeListener(event, fn, context, once);

/**
 * Remove all listeners, or those of the specified event
 * @param {string|symbol} [event] - The event name (removes all events if omitted)
 * @returns {EventEmitter} this - For method chaining
 */
removeAllListeners(event);

/**
 * Alias for on()
 */
addListener(event, fn, context);

/**
 * Alias for removeListener()
 */
off(event, fn, context, once);

Usage Example:

const emitter = new EventEmitter();
const context = { userId: 123 };

function handleData(data) {
  console.log(`User ${this.userId} received:`, data);
}

// Add listener with context
emitter.on('data', handleData, context);

// Emit event - listener called with context
emitter.emit('data', 'message'); // User 123 received: message

// Remove specific listener
emitter.removeListener('data', handleData, context);

Event Emission

Emit events to all registered listeners with optimized argument handling.

/**
 * Calls each of the listeners registered for a given event
 * Optimized for up to 6 arguments for performance
 * @param {string|symbol} event - The event name
 * @param {...*} args - Arguments to pass to listeners
 * @returns {boolean} true if the event had listeners, false otherwise
 */
emit(event, ...args);

Usage Example:

const emitter = new EventEmitter();

emitter.on('message', (text, priority, timestamp) => {
  console.log(`[${priority}] ${timestamp}: ${text}`);
});

// Emit with multiple arguments
const hasListeners = emitter.emit('message', 'Hello', 'high', Date.now());
console.log('Event had listeners:', hasListeners); // true

Event Introspection

Query information about registered listeners and events.

/**
 * Return an array listing the events for which the emitter has registered listeners
 * @returns {Array<string|symbol>} Array of event names
 */
eventNames();

/**
 * Return the listeners registered for a given event
 * @param {string|symbol} event - The event name
 * @returns {Function[]} Array of listener functions
 */
listeners(event);

/**
 * Return the number of listeners listening to a given event
 * @param {string|symbol} event - The event name
 * @returns {number} Number of listeners
 */
listenerCount(event);

Usage Example:

const emitter = new EventEmitter();

emitter.on('data', () => {});
emitter.on('error', () => {});
emitter.once('ready', () => {});

console.log(emitter.eventNames()); // ['data', 'error', 'ready']
console.log(emitter.listenerCount('data')); // 1
console.log(emitter.listeners('data')); // [function]

Static Properties

Access EventEmitter configuration and constructor reference.

/**
 * Indicates if event names are prefixed for compatibility
 * @type {string|boolean} Either '~' or false
 */
EventEmitter.prefixed;

/**
 * Reference to EventEmitter constructor (module namespace object)
 * @type {Function} EventEmitter constructor
 */
EventEmitter.EventEmitter;

Usage Example:

console.log(EventEmitter.prefixed); // '~' or false
console.log(EventEmitter.EventEmitter === EventEmitter); // true

TypeScript Support

EventEmitter3 includes comprehensive TypeScript definitions with generic type support.

interface ValidEventTypes = string | symbol | object;

interface EventEmitter<EventTypes = string | symbol, Context = any> {
  eventNames(): Array<EventNames<EventTypes>>;
  listeners<T extends EventNames<EventTypes>>(
    event: T
  ): Array<EventListener<EventTypes, T>>;
  listenerCount(event: EventNames<EventTypes>): number;
  emit<T extends EventNames<EventTypes>>(
    event: T,
    ...args: EventArgs<EventTypes, T>
  ): boolean;
  on<T extends EventNames<EventTypes>>(
    event: T,
    fn: EventListener<EventTypes, T>,
    context?: Context
  ): this;
  once<T extends EventNames<EventTypes>>(
    event: T,
    fn: EventListener<EventTypes, T>,
    context?: Context
  ): this;
  removeListener<T extends EventNames<EventTypes>>(
    event: T,
    fn?: EventListener<EventTypes, T>,
    context?: Context,
    once?: boolean
  ): this;
  removeAllListeners(event?: EventNames<EventTypes>): this;
  addListener<T extends EventNames<EventTypes>>(
    event: T,
    fn: EventListener<EventTypes, T>,
    context?: Context
  ): this;
  off<T extends EventNames<EventTypes>>(
    event: T,
    fn?: EventListener<EventTypes, T>,
    context?: Context,
    once?: boolean
  ): this;
}

// Type helpers
type EventNames<T extends ValidEventTypes> = T extends string | symbol ? T : keyof T;
type EventListener<T extends ValidEventTypes, K extends EventNames<T>> = 
  T extends string | symbol 
    ? (...args: any[]) => void
    : (...args: ArgumentMap<Exclude<T, string | symbol>>[Extract<K, keyof T>]) => void;
type EventArgs<T extends ValidEventTypes, K extends EventNames<T>> = 
  Parameters<EventListener<T, K>>;

TypeScript Usage Examples:

// Define event interface
interface AppEvents {
  'user-login': [userId: string, timestamp: number];
  'user-logout': [userId: string];
  'error': [error: Error];
  'ready': [];
}

const emitter = new EventEmitter<AppEvents>();

// Type-safe event handling
emitter.on('user-login', (userId, timestamp) => {
  // userId and timestamp are properly typed
  console.log(`User ${userId} logged in at ${timestamp}`);
});

emitter.on('error', (error) => {
  // error is typed as Error
  console.error('Application error:', error.message);
});

// Type-safe emission
emitter.emit('user-login', 'user123', Date.now()); // ✓ Valid
emitter.emit('user-login', 'user123'); // ✗ TypeScript error - missing timestamp

Error Handling

EventEmitter3 does not throw errors when emitting error events with no listeners, unlike Node.js EventEmitter.

const emitter = new EventEmitter();

// This does NOT throw an error (unlike Node.js EventEmitter)
emitter.emit('error', new Error('Something went wrong')); // Returns false

// To handle errors properly, always add an error listener
emitter.on('error', (err) => {
  console.error('Caught error:', err);
});

emitter.emit('error', new Error('Something went wrong')); // Returns true, handled

Performance Considerations

EventEmitter3 is optimized for high-performance scenarios:

  • Argument optimization: Special handling for 1-6 arguments to avoid arguments object
  • Single vs multiple listeners: Different code paths for single and multiple listeners
  • Context binding: Built-in context support eliminates fn.bind() overhead
  • ECMAScript 3: Compatible with older environments while maintaining performance
// Optimized usage patterns
const emitter = new EventEmitter();

// Fast path - uses optimized argument handling
emitter.emit('event', arg1, arg2, arg3, arg4, arg5); // ✓ Optimized

// Context without binding overhead
emitter.on('event', handler, context); // ✓ Better than handler.bind(context)

// Efficient listener management
emitter.once('init', () => {}); // ✓ Automatic cleanup after first emission