Facebook's EventEmitter is a simple emitter implementation that prioritizes speed and simplicity
npx @tessl/cli install tessl/npm-fbemitter@3.0.0Facebook's EventEmitter is a simple emitter implementation that prioritizes speed and simplicity. It provides a subscription-based listener management system where each added listener returns a subscription token that can be used to cleanly remove the listener.
npm install fbemittervar {EventEmitter} = require('fbemitter');
// or
var fbemitter = require('fbemitter');
var EventEmitter = fbemitter.EventEmitter;For ES6 modules:
import {EventEmitter} from 'fbemitter';var {EventEmitter} = require('fbemitter');
// Create a new emitter
var emitter = new EventEmitter();
// Add a listener - returns a subscription token
var subscription = emitter.addListener('event', function(x, y) {
console.log(x, y);
});
// Emit an event
emitter.emit('event', 5, 10); // Listener prints "5 10"
// Remove the specific listener
subscription.remove();
// Add a one-time listener
var onceSubscription = emitter.once('event', function(data) {
console.log('One time:', data);
});
// Remove all listeners for an event type
emitter.removeAllListeners('event');Creates a new EventEmitter instance.
/**
* Creates a new EventEmitter instance
*/
constructor(): EventEmitterAdds a listener to be invoked when events of the specified type are emitted. Returns a subscription token for removal.
/**
* Adds a listener for the specified event type
* @param {string} eventType - Name of the event to listen to
* @param {function} listener - Function to invoke when the event is emitted
* @param {?Object} [context] - Optional context object for listener invocation
* @returns {EmitterSubscription} Subscription token for removing the listener
*/
addListener(eventType: string, listener: function, context?: ?Object): EmitterSubscriptionSimilar to addListener, but the listener is automatically removed after it is invoked once.
/**
* Adds a listener that is automatically removed after first invocation
* @param {string} eventType - Name of the event to listen to
* @param {function} listener - Function to invoke only once
* @param {?Object} [context] - Optional context object for listener invocation
* @returns {EmitterSubscription} Subscription token for removing the listener
*/
once(eventType: string, listener: function, context?: ?Object): EmitterSubscriptionRemoves all registered listeners for a given event type, or all listeners if no event type is specified.
/**
* Removes all registered listeners for given event type or all events
* @param {string} [eventType] - Optional event type to target, removes all if not specified
*/
removeAllListeners(eventType?: string): voidRemoves the currently executing listener. Critical constraint: Can only be called during an event emission cycle - throws an Error if called outside of an emit.
/**
* Removes the currently executing listener (only callable during emit cycle)
* @throws {Error} "Not in an emitting cycle; there is no current subscription" when called outside of an emitting cycle
*/
removeCurrentListener(): voidReturns an array of listener functions currently registered for the given event type.
/**
* Returns array of listeners currently registered for given event type
* @param {string} eventType - Name of the event to query
* @returns {Array<function>} Array of listener functions
*/
listeners(eventType: string): Array<function>Emits an event of the given type with the provided arguments. All registered listeners for that event type will be notified.
/**
* Emits event of given type, notifying all registered listeners
* @param {string} eventType - Name of the event to emit
* @param {...*} args - Arbitrary arguments passed to each listener
*/
emit(eventType: string, ...args: any): voidProvides a hook to override how the emitter emits an event to a specific subscription. Useful for custom logging or error boundaries.
/**
* Hook for custom logging/error handling during listener invocation
* @param {EmitterSubscription} subscription - The subscription being invoked
* @param {string} eventType - Name of the event being emitted
* @param {...*} args - Arguments to pass to listener
*/
__emitToSubscription(subscription: EmitterSubscription, eventType: string, ...args: any): voidRepresents a subscription with listener and context data. Extends EventSubscription.
/**
* Subscription wrapper that holds listener function and context
*/
class EmitterSubscription extends EventSubscription {
/**
* @param {EventSubscriptionVendor} subscriber - The vendor managing this subscription
* @param {function} listener - The listener function
* @param {?Object} [context] - Optional context for listener invocation
*/
constructor(subscriber: EventSubscriptionVendor, listener: function, context?: ?Object);
/** The listener function */
listener: function;
/** Optional context object */
context?: ?Object;
/**
* Removes this subscription from its managing emitter
*/
remove(): void;
}Main event emitter class for managing listeners and emitting events.
class EventEmitter {
constructor();
addListener(eventType: string, listener: function, context?: ?Object): EmitterSubscription;
once(eventType: string, listener: function, context?: ?Object): EmitterSubscription;
removeAllListeners(eventType?: string): void;
removeCurrentListener(): void;
listeners(eventType: string): Array<function>;
emit(eventType: string, ...args: any): void;
__emitToSubscription(subscription: EmitterSubscription, eventType: string, ...args: any): void;
}var {EventEmitter} = require('fbemitter');
var emitter = new EventEmitter();
// Basic listener
var sub1 = emitter.addListener('change', function(data) {
console.log('Data changed:', data);
});
// Listener with context
var context = { name: 'MyHandler' };
var sub2 = emitter.addListener('change', function(data) {
console.log(this.name + ' received:', data);
}, context);
emitter.emit('change', {value: 42});
// Output: "Data changed: {value: 42}"
// Output: "MyHandler received: {value: 42}"var subscription = emitter.once('init', function() {
console.log('Initialized!');
});
emitter.emit('init'); // logs "Initialized!"
emitter.emit('init'); // nothing logged - listener was removed// Add multiple listeners
var sub1 = emitter.addListener('event', handler1);
var sub2 = emitter.addListener('event', handler2);
var sub3 = emitter.addListener('other', handler3);
// Remove specific listener
sub1.remove();
// Remove all listeners for 'event'
emitter.removeAllListeners('event');
// Remove all listeners
emitter.removeAllListeners();class MyEventEmitter extends EventEmitter {
__emitToSubscription(subscription, eventType) {
var args = Array.prototype.slice.call(arguments, 2);
try {
subscription.listener.apply(subscription.context, args);
} catch (error) {
console.error('Error in listener for', eventType, ':', error);
}
}
}
var emitter = new MyEventEmitter();
emitter.addListener('event', function() {
throw new Error('Something went wrong!');
});
emitter.emit('event'); // Error is caught and loggedremoveCurrentListener() throws an Error with message "Not in an emitting cycle; there is no current subscription" when called outside of an emitting cyclefbjs/lib/invariant for subscription management integrity__emitToSubscription() to wrap listener invocation in try/catch blocks__emitToSubscription() implementation