Simple event emitter.
npm i @for-fun/event-emitterimport * as React from 'react';
import {create, on, emit} from '@for-fun/event-emitter';
const emitter = create();
export default function() {
const [message, setMessage] = React.useState('');
React.useEffect(() => on(emitter, 'message', setMessage));
return <div>
<p>{message}</p>
<button onClick={() => emit(emitter, 'message', 'hello')}>Click Me</button>
</div>;
}This lib support these browsers or devices with these methods or APIs pollyfilled.
Wildcard subscriptions (e.g. on(ee, '*', handler)) are not supported by design. Path-level or hierarchical subscriptions are a consumer-side concern — for example, react-f0rm builds them on top of this emitter via onPathEvent.
on/once return an OffFunction that removes that exact subscription:
const off = on(ee, 'message', handler);
off(); // removes this exact subscriptionAdditionally, off and removeAllListeners remove listeners in bulk:
off(ee, 'message', handler); // removes one exact subscription
off(ee, 'message'); // removes every 'message' listener
off(ee); // removes every listener of every key
removeAllListeners(ee, 'message'); // same as off(ee, 'message')
removeAllListeners(ee); // same as off(ee)Both are no-ops for keys or handlers that were never subscribed.
Handlers of one emit are independent: if a handler throws, the remaining
handlers of that same emit still run. The collected errors are reported
one by one to the errorEvent channel (onError/onceError
subscribers). If no error handler is subscribed either, emit rethrows
the first collected error, so failures are never silently swallowed:
onError(ee, err => report(err)); // receives every collected error
emit(ee, 'a'); // throws the first error only when no error handler existsWhen more than 10 listeners accumulate on one key — a common symptom of a
missing unsubscribe — a console.warn fires once per key, in development
only:
setMaxListeners(ee, 20); // raise the limit for this emitter
setMaxListeners(ee, 0); // disable the warning for this emitterThe gate is process.env.NODE_ENV !== 'production' (also silent when
process is unavailable, e.g. the UMD build loaded directly in a
browser). Production builds skip the whole check; on only pays a single
boolean test.
emit iterates the key's handler set with Set semantics:
- a listener added while an emit is running is invoked by that same emit (Set iteration visits entries appended mid-iteration);
- a listener removed before the iteration reaches it is skipped;
- removing a whole key (
off(ee, key)/removeAllListeners(ee, key)) does not stop an emit that is already running.
# develop
npm start
# build
npm run build
# test
npm test
# commit changes
npm run commit
# publish
npm publish