An isomorphic event emitter with type safety! (Inspired by emittery)
npm install better-eventimport { createEventEmitter } from 'better-event';
const emitter = createEventEmitter({
on: {
hello: (data: string) => {
console.log('hello', data);
},
},
});
await emitter.emit('hello', 'world');
// => hello world- register event listeners when initializing
- disable event listeners with disable()
- timeout support for event handlers
- abort event listeners with AbortSignal
- type-safe event listener registration and emission
Important
This project is currently in its early stages.
Breaking changes may happen in every version without notice until v1.0.0.
-
Step 1: Initialize the event emitter
import { createEventEmitter } from 'better-event'; const emitter = createEventEmitter();
-
Step 2: Add callback function with custom event key
import { createEventEmitter } from 'better-event'; const emitter = createEventEmitter({ on: { // 'hello' is the event key hello: () => { console.log('hello'); }, }, });
-
Step 3 (optional): pass the data to the event callback function
import { createEventEmitter } from 'better-event'; const emitter = createEventEmitter({ on: { hello: (name: string) => { console.log('hello', name); }, }, });
-
Step 4: Emit the event:
import { createEventEmitter } from 'better-event'; const emitter = createEventEmitter({ on: { hello: () => { console.log('hello'); }, }, }); await emitter.emit('hello'); // => hello
create an event emitter:
-
handler: the event handler function to call when the event is emitted
-
handler: (data: T) => Promise<void> | voidExample:
const emitter = createEventEmitter({ on: { hello: (data: string) => { console.log('hello', data); }, }, });
-
-
signal: (optional) an AbortSignal to abort the event listener
-
signal?: AbortSignalExample:const controller = new AbortController(); const signal = controller.signal; const emitter = createEventEmitter({ on: { hello: { handler: async (data: string) => { console.log('hello', data); }, signal, }, }, }); controller.abort(); await emitter.emit('hello', 'world'); // nothing happens
-
-
timeout: (optional) the maximum time in milliseconds to wait for the event handler to complete
-
timeout?: numberThrowsTimeoutErrorif the handler does not complete within the specified time.Example:
import { createEventEmitter, TimeoutError } from 'better-event'; const emitter = createEventEmitter({ on: { hello: { handler: async (data: string) => { await new Promise((resolve) => setTimeout(resolve, 1000)); console.log('hello', data); }, timeout: 100, }, }, }); try { await emitter.emit('hello', 'world'); } catch (error) { console.error(error.message); // => Event hello timed out }
-
(optional) a name for the event to be console.log() when event is emitted
debug?: {name: string}-
Example:
const emitter = createEventEmitter({ on: { hello: (data: string) => { console.log('hello', data); }, }, debug: { name: 'hello' }, }); await emitter.emit('hello', 'world'); // => hello world // => { // time: "6/6/2026, 2:23:27 PM", // name: "hello", // eventKey: "hello", // data: "world", // }
-
Emit an event with the key and optional data. The data argument can be omitted if the handler takes no parameters.
Error: TimeoutError with properties:
.timeout— the configured timeout duration in milliseconds.eventKey— the key of the event that timed out
Example:
const emitter = createEventEmitter({
on: {
hello: () => {
console.log('hello world');
},
},
});
await emitter.emit('hello');
// => hello worldDisable an event listener. After disabling, emitting the event does nothing.
Example:
const emitter = createEventEmitter({
on: {
hello: () => {
console.log('hello world');
},
},
});
await emitter.emit('hello');
// => hello world
emitter.disable('hello');
await emitter.emit('hello');
// nothing happens- Install dependencies:
bun install- Run the unit tests:
bun run test- Build the library:
bun run build