https://github.com/alessiofrittoli/event-emitter
Cross-env TypeScript Event Emitter
https://github.com/alessiofrittoli/event-emitter
event-emitter events
Last synced: 2 months ago
JSON representation
Cross-env TypeScript Event Emitter
- Host: GitHub
- URL: https://github.com/alessiofrittoli/event-emitter
- Owner: alessiofrittoli
- License: mit
- Created: 2025-01-03T21:45:11.000Z (5 months ago)
- Default Branch: master
- Last Pushed: 2025-03-21T11:59:22.000Z (3 months ago)
- Last Synced: 2025-04-15T05:47:47.672Z (2 months ago)
- Topics: event-emitter, events
- Language: TypeScript
- Homepage: https://npmjs.com/package/@alessiofrittoli/event-emitter
- Size: 202 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: license.md
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Event Emitter 🔊
[![NPM Latest Version][version-badge]][npm-url] [![Coverage Status][coverage-badge]][coverage-url] [![Socket Status][socket-badge]][socket-url] [![NPM Monthly Downloads][downloads-badge]][npm-url] [![Dependencies][deps-badge]][deps-url]
[![GitHub Sponsor][sponsor-badge]][sponsor-url]
[version-badge]: https://img.shields.io/npm/v/%40alessiofrittoli%2Fevent-emitter
[npm-url]: https://npmjs.org/package/%40alessiofrittoli%2Fevent-emitter
[coverage-badge]: https://coveralls.io/repos/github/alessiofrittoli/event-emitter/badge.svg
[coverage-url]: https://coveralls.io/github/alessiofrittoli/event-emitter
[socket-badge]: https://socket.dev/api/badge/npm/package/@alessiofrittoli/event-emitter
[socket-url]: https://socket.dev/npm/package/@alessiofrittoli/event-emitter/overview
[downloads-badge]: https://img.shields.io/npm/dm/%40alessiofrittoli%2Fevent-emitter.svg
[deps-badge]: https://img.shields.io/librariesio/release/npm/%40alessiofrittoli%2Fevent-emitter
[deps-url]: https://libraries.io/npm/%40alessiofrittoli%2Fevent-emitter[sponsor-badge]: https://img.shields.io/static/v1?label=Fund%20this%20package&message=%E2%9D%A4&logo=GitHub&color=%23DB61A2
[sponsor-url]: https://github.com/sponsors/alessiofrittoli## Cross-env TypeScript Event Emitter
A cross-environment implementation of an `EventEmitter` that works seamlessly in **Node.js**, **Edge Runtime** (such as Next.js middleware), and **browser** environments.
The `EventEmitter` class provides a mechanism to handle events and their listeners.
It allows you to register event listeners, emit events, and manage the listeners for those events.### Table of Contents
- [Getting started](#getting-started)
- [API Reference](#api-reference)
- [`EventEmitter` Class](#eventemitter-class)
- [Constructor](#constructor)
- [Methods](#methods)
- [Types](#types)
- [Examples](#examples)
- [Development](#development)
- [Install depenendencies](#install-depenendencies)
- [Build the source code](#build-the-source-code)
- [ESLint](#eslint)
- [Jest](#jest)
- [Contributing](#contributing)
- [Security](#security)
- [Credits](#made-with-)---
### Getting started
Run the following command to start using `event-emitter` in your projects:
```bash
npm i @alessiofrittoli/event-emitter
```or using `pnpm`
```bash
pnpm i @alessiofrittoli/event-emitter
```---
### API Reference
#### `EventEmitter` Class
##### Constructor
```ts
new EventEmitter( options?: EventEmitterOptions )
```Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `options` | `EventEmitterOptions` | - | Optional configuration object for the emitter instance. |
| `options.captureRejections` | `boolean` | `false` | If set to `true`, captures and handles promise rejections in listeners. |---
##### Methods
###### `EventEmitter.emit()`
Emits an event to all registered listeners.
Parameters
| Parameter | Type | Description |
|-----------|--------------|----------------------------------------|
| `event` | `K` | The event name to emit. |
| `args` | `Args` | The arguments passed to the listeners. |---
###### `EventEmitter.on()`
Adds a listener for the specified event.
Parameters
| Parameter | Type | Description |
|------------|------------------|---------------------------------------------------------|
| `event` | `K` | The event name to listen for. |
| `listener` | `Listener` | The listener function called when the event is emitted. |---
Returns
Type: `EventEmitter`
The current `EventEmitter` instance so that calls can be chained.
---
###### `EventEmitter.addListener()`
Alias for `EventEmitter.on( event, listener )`.
---
###### `EventEmitter.prepend()`
Adds a listener to the beginning of the listener array for the specified event.
Parameters
| Parameter | Type | Description |
|------------|------------------|---------------------------------------------------------|
| `event` | `K` | The event name to listen for. |
| `listener` | `Listener` | The listener function called when the event is emitted. |---
Returns
Type: `EventEmitter`
The current `EventEmitter` instance so that calls can be chained.
---
###### `EventEmitter.prependListener()`
Alias for `EventEmitter.prepend( event, listener )`.
---
###### `EventEmitter.once()`
Adds a one-time listener for the specified event. Even if the event is emitted multiple times, listeners registered with `.once()` method will only get called one single time.
Parameters
| Parameter | Type | Description |
|------------|------------------|---------------------------------------------------------|
| `event` | `K` | The event name to listen for. |
| `listener` | `Listener` | The listener function called when the event is emitted. |---
Returns
Type: `EventEmitter`
The current `EventEmitter` instance so that calls can be chained.
---
###### `EventEmitter.prependOnce()`
Adds a one-time listener to the beginning of the listener array for the specified event.
Parameters
| Parameter | Type | Description |
|------------|------------------|---------------------------------------------------------|
| `event` | `K` | The event name to listen for. |
| `listener` | `Listener` | The listener function called when the event is emitted. |---
Returns
Type: `EventEmitter`
The current `EventEmitter` instance so that calls can be chained.
---
###### `EventEmitter.prependOnceListener()`
Alias for `EventEmitter.prependOnce( event, listener )`.
---
###### `EventEmitter.off()`
Removes a listener for the specified event.
Parameters
| Parameter | Type | Description |
|------------|------------------|---------------------------------------------------------|
| `event` | `K` | The event name to remove the listener from. |
| `listener` | `Listener` | The listener function to remove from the given `event`. |---
Returns
Type: `EventEmitter`
The current `EventEmitter` instance so that calls can be chained.
---
###### `EventEmitter.removeListener()`
Alias for `EventEmitter.off( event, listener )`.
---
###### `EventEmitter.removeAllListeners()`
Removes all listeners for a specified event or all events.
Parameters
| Parameter | Type | Description |
|------------|------------------|---------------------------------------------------------|
| `event` | `K` | (Optional) The event name to remove listeners from. |
| `listener` | `Listener` | (Optional) The listener function to remove. |---
Returns
Type: `EventEmitter`
The current `EventEmitter` instance so that calls can be chained.
---
###### `EventEmitter.getMaxListeners()`
Gets the current maximum number of listeners. Default: `EventEmitter.defaultMaxListeners` (10).
Returns
Type `number`
The current maximum number of listeners.
---
###### `EventEmitter.setMaxListeners()`
Sets the maximum number of listeners allowed for each event.
By default, a maximum of `10` listeners can be registered for any single event. This limit can be changed for individual `EventEmitter` instances using the `EventEmitter.setMaxListeners( n )` method.
This is not a hard limit. The `EventEmitter` instance will allow more listeners to be added but will output a trace warning to stderr indicating that a "possible EventEmitter memory leak" has been detected.
Parameters
| Parameter | Type | Description |
|-----------|----------|----------------------------------|
| `n` | `number` | The maximum number of listeners. |---
Returns
Type: `EventEmitter`
The current `EventEmitter` instance so that calls can be chained.
---
###### `EventEmitter.listenerCount()`
Gets the number of listeners for the specified event.
Parameters
| Parameter | Type | Description |
|------------|------------------|----------------------------------------------------------|
| `event` | `K` | The event name to check the listeners for. |
| `listener` | `Listener` | (Optional) The specific listener to count (if provided). |---
Returns
Type: `number`
The number of listeners for the specified event and optionally for the given listener.
---
###### `EventEmitter.listeners()`
Returns a list of listeners for the specified event.
Parameters
| Parameter | Type | Description |
|-----------|------|--------------------------------------|
| `event` | `K` | The event name to get listeners for. |---
Returns
Type: `( Listener )[]`
An array of registered listeners. Even if the listener is registered using the `.once()` method, the actual listener is returned instead of the `OnceListenerWrapper`.
---
###### `EventEmitter.rawListeners()`
Returns a copy of the array of listeners for the specified event, including any wrappers (such as those created by `.once()`).
Parameters
| Parameter | Type | Description |
|-----------|------|--------------------------------------|
| `event` | `K` | The event name to get listeners for. |---
Returns
Type: `( Listener | OnceListenerWrapper )[]`
An array of registered listener callback.
If a listener has been registered using the `.once()` method a `OnceListenerWrapper` is returned. In that case the original listener can be retrieved through the `listener` property.
---
###### `EventEmitter.eventNames()`
Returns a list of all event names.
Returns
Type: `( keyof T )[]`
An array of registered event names.
---
#### Types
##### `EventEmitterOptions`
Options for configuring the `EventEmitter`.
Properties
| Proeprty | Type | Description |
|---------------------|-----------|-------------|
| `captureRejections` | `boolean` | If set to true, captures and handles promise rejections in listeners. |---
##### `Listener`
Defines the type of a listener function.
Properties
| Proeprty | Type | Description |
|----------|--------------|-------------|
| `args` | `Args` | Arguments passed to the listener corresponding to the event key. |---
##### `OnceListenerWrapper`
A wrapper for listeners that should be invoked only once.
Properties
| Proeprty | Type | Description |
|------------|------------------|-------------|
| `args` | `Args` | Arguments passed to the listener corresponding to the event key. |
| `listener` | `Listener` | The actual listener function to be invoked. |---
##### `Args`
A utility type that resolves to a specific type based on the provided keys and event map.
---
#### Examples
##### Defining custom types
Details
```ts
import type { Listener } from '@alessiofrittoli/event-emitter'// Define an event map for your EventEmitter
interface MyEvents
{
greet : [ name: string ] // The 'greet' event takes a string argument
farewell : [ name: Error ] // The 'farewell' event also takes a string argument
error : [ error: Error ] // The 'error' event takes an Error argument
}// Optionally define listeners types
type OnGreetEventListener = Listener
type OnFarewellEventListener = Listener
type OnErrorEventListener = Listener
```---
##### Emitting and Listening events
Declaring listeners
```ts
const greetListener: OnGreetEventListener = name => {
console.log( `Hello, ${ name }!` )
}const farewellListener: OnFarewellEventListener = name => {
console.log( `Goodbye, ${ name }!` )
}const errorListener: OnErrorEventListener = error => {
console.error( 'Something went wrong.', error.message )
}
```---
Registering listeners and emitting events
```ts
import { EventEmitter } from '@alessiofrittoli/event-emitter'const emitter = new EventEmitter()
// Attach listeners
emitter.on( 'greet', greetListener )
emitter.on( 'farewell', farewellListener )
emitter.on( 'error', errorListener )// Emit events
emitter.emit( 'greet', 'Foo' )
emitter.emit( 'farewell', 'Bar' )
emitter.emit( 'error', new Error( 'An error occured.' ) )
```---
##### One-time events listeners
Details
```ts
const emitter = new EventEmitter()// Define a listener for the 'greet' event that should only be called once
const greetOnceListener: OnGreetEventListener = name => {
console.log( `Once Hello, ${ name }!` )
}emitter.once( 'greet', greetOnceListener )
// Emit the event
emitter.emit( 'greet', 'Foo' )
// `greetOnceListener` won't be called anymore, as the listener was removed after the first call.
emitter.emit( 'greet', 'Bob' )
```---
##### Error Handling with `captureRejections`
Details
```ts
const emitter = new EventEmitter( { captureRejections: true } )const greetListener: OnGreetEventListener = name => {
if ( name === 'He-Who-Must-Not-Be-Named' ) {
throw new Error( 'nooose!' )
}
console.log( `Howdy, ${ name }!` )
}const errorListener: OnErrorEventListener = error => {
console.error( 'Caught your', error.message )
}// Add listeners
emitter.on( 'greet', greetListener )
emitter.on( 'error', errorListener )// Emit events
emitter.emit( 'greet', 'Foo' )
emitter.emit( 'greet', 'He-Who-Must-Not-Be-Named' )
```---
##### Managing Max Listeners
Details
```ts
const emitter = (
new EventEmitter()
.setMaxListeners( 1 )
)const greetListener1: OnGreetEventListener = name => {
console.log( `Hello, ${ name }!` )
}const greetListener2: OnGreetEventListener = name => {
console.log( `Hi, ${ name }!` )
}const greetListener3: OnGreetEventListener = name => {
console.log( `Howdy, ${ name }!` )
}// Attach listeners
emitter.on( 'greet', greetListener1 )
emitter.on( 'greet', greetListener2 ) // This will trigger a warning but it will get executed anyway.
emitter.on( 'greet', greetListener3 ) // This won't trigger a warning. Warnings are emitted once.emitter.emit( 'greet', 'Foo' )
// Output:
// Hello, Foo!
// Hi, Foo!
// Howdy, Foo!
```---
##### Using `prepend` and `prependOnce`
Details
```ts
const emitter = new EventEmitter()// Attach listeners
emitter.on( 'greet', name => {
console.log( `A: Hello! Better late than never ${ name }.` )
} )
emitter.prepend( 'greet', name => {
console.log( `B: Hello, ${ name }!` )
} )
emitter.prependOnce( 'greet', name => {
console.log( `C: Once Hello, ${ name }! I won't say hello to you, Bar.` )
} )// Emit events
emitter.emit( 'greet', 'Foo' )
emitter.emit( 'greet', 'Bar' )
// Outputs:
// C: Once Hello, Foo! I won't say hello to you, Bar.
// B: Hello, Foo!
// A: Hello! Better late than never Foo.
// B: Hello, Bar!
// A: Hello! Better late than never Bar.
```---
##### Retrieve listeners count
Get listeners count for a specific event
```ts
const emitter = (
new EventEmitter()
.on( 'greet', () => {} )
.on( 'greet', () => {} )
.on( 'farewell', () => {} )
)console.log( emitter.listenerCount( 'greet' ) ) // Outputs: `2`
console.log( emitter.listenerCount( 'farewell' ) ) // Outputs: `1`
console.log( emitter.listenerCount( 'error' ) ) // Outputs: `0`
```---
Get listeners count for a specific event and listener
```ts
const callback1 = () => {}
const callback2 = () => {}const emitter = (
new EventEmitter()
.on( 'greet', callback1 )
.on( 'greet', callback1 )
.on( 'greet', callback2 )
)console.log( emitter.listenerCount( 'greet', callback1 ) ) // Outputs: `2`
console.log( emitter.listenerCount( 'greet', callback2 ) ) // Outputs: `1`
```---
##### Retrieve registered listeners
Get registerd listeners array
We register `callback2` with `EventEmitter.once()` to verify that we correctly get the original `callback2` instead of the `onceWrapper` function in the returning array.
```ts
const callback1 = () => {}
const callback2 = () => {}const emitter = (
new EventEmitter()
.on( 'greet', callback1 )
.once( 'greet', callback2 )
.on( 'farewell', callback1 )
)
const functions = emitter.listeners( 'greet' ) // Listener[]console.log( functions )
// Outputs: `[ [Function: callback1], [Function: callback2] ]`functions.map( listener => {
listener() // manually execute the listener.
} )
```---
Get registerd raw listeners array
Again we register `callback2` with `EventEmitter.once()` to verify that we correctly get the `onceWrapper` function instead of the original `callback2` listener in the returning array.
```ts
const callback1 = () => {}
const callback2 = () => {}const emitter = (
new EventEmitter()
.on( 'greet', callback1 )
.once( 'greet', callback2 )
.on( 'farewell', callback1 )
)const functions = emitter.rawListeners( 'greet' ) // ( Listener | OnceListenerWrapper )[]
console.log( functions )
// Outputs: `[ [Function: callback1], [Function: onceWrapper] { listener: [Function: callback2] } ]`functions.map( callback => {
/** Manually execute the listener. If this is a `onceWrapper` function, it will remove the listener from the listeners array and then execute the original listener function. */
callback()/** Or execute the original listener without removing it from the listeners array. */
if ( 'listener' in callback ) {
callback.listener()
}
} )
```---
##### Batch removing listeners
Remove all attached listeners to every registered event
```ts
const emitter = (
new EventEmitter()
.on( 'greet', () => {} )
.once( 'greet', () => {} )
.on( 'farewell', () => {} )
)console.log( emitter.listenerCount( 'greet' ) ) // Outputs: `2`
console.log( emitter.listenerCount( 'farewell' ) ) // Outputs: `1`
console.log( emitter.listenerCount( 'error' ) ) // Outputs: `0`emitter.removeAllListeners()
console.log( emitter.listenerCount( 'greet' ) ) // Outputs: `0`
console.log( emitter.listenerCount( 'farewell' ) ) // Outputs: `0`
console.log( emitter.listenerCount( 'error' ) ) // Outputs: `0`
```---
Remove all attached listeners to a specific event
```ts
const emitter = (
new EventEmitter()
.on( 'greet', () => {} )
.once( 'greet', () => {} )
.on( 'farewell', () => {} )
.removeAllListeners( 'greet' )
)console.log( emitter.listenerCount( 'greet' ) ) // Outputs: `0`
console.log( emitter.listenerCount( 'farewell' ) ) // Outputs: `1`
console.log( emitter.listenerCount( 'error' ) ) // Outputs: `0`
```---
Remove specifc listeners attached to a specific event
```ts
const callback1 = () => {}
const callback2 = () => {}const emitter = (
new EventEmitter()
.on( 'greet', callback1 )
.once( 'greet', callback1 )
.once( 'greet', callback2 )
.on( 'farewell', callback1 )
.removeAllListeners( 'greet', callback1 )
)console.log( emitter.listenerCount( 'greet' ) ) // Outputs: `1`
console.log( emitter.listenerCount( 'farewell' ) ) // Outputs: `1`
console.log( emitter.listenerCount( 'error' ) ) // Outputs: `0`
```---
### Development
#### Install depenendencies
```bash
npm install
```or using `pnpm`
```bash
pnpm i
```#### Build the source code
Run the following command to test and build code for distribution.
```bash
pnpm build
```#### [ESLint](https://www.npmjs.com/package/eslint)
warnings / errors check.
```bash
pnpm lint
```#### [Jest](https://npmjs.com/package/jest)
Run all the defined test suites by running the following:
```bash
# Run tests and watch file changes.
pnpm test:watch# Run tests in a CI environment.
pnpm test:ci
```- See [`package.json`](./package.json) file scripts for more info.
Run tests with coverage.
An HTTP server is then started to serve coverage files from `./coverage` folder.
⚠️ You may see a blank page the first time you run this command. Simply refresh the browser to see the updates.
```bash
test:coverage:serve
```---
### Contributing
Contributions are truly welcome!
Please refer to the [Contributing Doc](./CONTRIBUTING.md) for more information on how to start contributing to this project.
Help keep this project up to date with [GitHub Sponsor][sponsor-url].
[![GitHub Sponsor][sponsor-badge]][sponsor-url]
---
### Security
If you believe you have found a security vulnerability, we encourage you to **_responsibly disclose this and NOT open a public issue_**. We will investigate all legitimate reports. Email `[email protected]` to disclose any security vulnerabilities.
### Made with ☕
![]()
Alessio Frittoli
https://alessiofrittoli.it |
[email protected]