{"id":26432400,"url":"https://github.com/33j33/buffered-event-emitter","last_synced_at":"2025-10-17T02:53:45.948Z","repository":{"id":60081604,"uuid":"540946767","full_name":"33j33/buffered-event-emitter","owner":"33j33","description":"Event emitter designed for handling rapid events - supports buffering, queueing, pausing, resuming events and caching of event data","archived":false,"fork":false,"pushed_at":"2025-06-27T19:00:51.000Z","size":479,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-09T02:47:35.129Z","etag":null,"topics":["buffering","event-emitter"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/33j33.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-09-24T19:38:16.000Z","updated_at":"2025-06-26T19:04:42.000Z","dependencies_parsed_at":"2025-05-30T21:08:41.558Z","dependency_job_id":"f7816d8e-cfd7-4cf9-8148-e8a9479b8312","html_url":"https://github.com/33j33/buffered-event-emitter","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/33j33/buffered-event-emitter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/33j33%2Fbuffered-event-emitter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/33j33%2Fbuffered-event-emitter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/33j33%2Fbuffered-event-emitter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/33j33%2Fbuffered-event-emitter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/33j33","download_url":"https://codeload.github.com/33j33/buffered-event-emitter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/33j33%2Fbuffered-event-emitter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278477817,"owners_count":25993540,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["buffering","event-emitter"],"created_at":"2025-03-18T06:18:21.653Z","updated_at":"2025-10-05T15:42:48.019Z","avatar_url":"https://github.com/33j33.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](https://badgen.net/badge/icon/typescript?icon=typescript\u0026label)\n![](https://badgen.net/npm/types/buffered-event-emitter)\n![](https://badgen.net/github/license/micromatch/micromatch)\n![](https://badgen.net/npm/dt/buffered-event-emitter)\n![](https://badgen.net/bundlephobia/dependency-count/buffered-event-emitter)\n![](https://badgen.net/bundlephobia/min/buffered-event-emitter)\n![](https://badgen.net/bundlephobia/minzip/buffered-event-emitter)\n\n# Buffered Event Emitter \u003c!-- omit in toc --\u003e\n\nBuffered Event Emitter is an enhanced event emission library built upon the familiar Node.js events API.\n\nWhile standard event emitters are good for basic publish-subscribe patterns, this library adds features for control over when and how listeners receive events, offering buffering, queueing, pause/resume capabilities, and caching.\n\n- Buffer events with configurable buffer capacity. \n- Pause and resume event emission.\n- Tiny, 2.3kb minzipped.\n- Works for both nodejs and browser.\n- Based on [node events api](https://nodejs.org/api/events.html)\n- Typescript support\n\n---\n\n### Key Features in Detail \u003c!-- omit in toc --\u003e\n\n**Event Buffering**: Handle rapid events by configuring listeners to buffer incoming data. Instead of invoking the listener for every single event emission, data is collected in a temporary buffer with optional automatic flushing. The listener is then invoked with the entire buffer as a batch once the buffer capacity is reached. This can be helpful for optimizing performance when dealing with processing events in chunks. You can set a global default buffer capacity or customize it per listener\n\n**Flow Control with Pause and Resume**: Gain fine-grained control over event emissions. You can pause emissions for the entire emitter instance or specifically for individual events. When paused, subsequent emit calls will not immediately invoke listeners.\n\n**Event Queueing**: When emissions are paused, you have the option to either swallow (discard) incoming events or queue them up. If queued, events are stored in order. When you resume, the queued events are processed sequentially, either synchronously or asynchronously with a configurable interval, ensuring no data is lost during temporary pauses.\n\n**Caching**: Automatically cache recent event data that has been emitted. The cache size is configurable, making it easy to access the recent event data.\n\n**Event Controllers for Listener Grouping**: Manage groups of related listeners using `EventController` instances. Attach multiple listeners across different event names or with different options to a single controller. Perform actions like flushing all associated buffered events or removing all associated listeners with a single call on the controller instance.\n\n**Optional Logging**: Easily trace when events are emitted, when listeners are added (on/once), and when listeners are removed (off). Logging can be enabled selectively for emit, on, and off actions.\n\n\n---\n\n## Table of Contents \u003c!-- omit in toc --\u003e\n\n- [Install](#install)\n- [Usage](#usage)\n  - [Usage in Node](#usage-in-node)\n  - [Usage in Browser](#usage-in-browser)\n- [API](#api)\n  - [new BufferedEventEmitter(options?)](#new-bufferedeventemitteroptions)\n  - [emit(eventName, data?)](#emiteventname-data)\n  - [on(eventName, listener, options?)](#oneventname-listener-options)\n  - [once(eventName, listener, options?)](#onceeventname-listener-options)\n  - [off(eventName, listener, options?)](#offeventname-listener-options)\n  - [flush(eventName, listener?, options?)](#flusheventname-listener-options)\n  - [new EventController()](#new-eventcontroller)\n  - [pause({queueEmissions?, emissionInterval?, eventName?})](#pausequeueemissions-emissioninterval-eventname)\n  - [resume(eventName?)](#resumeeventname)\n  - [enableDebug({ emit?, on?, off?})](#enabledebug-emit-on-off)\n  - [Types](#types)\n\n## Install\n\n```\nnpm install buffered-event-emitter\n```\n\n## Usage\n\n```typescript\nimport { BufferedEventEmitter } from \"buffered-event-emitter\";\nconst bEmitter = new BufferedEventEmitter();\n\nfunction ping(data: string) {\n  console.log(\"emitted data: \", data);\n}\n\nbEmitter.on(\"ping\", ping);\nbEmitter.emit(\"ping\", \"first emit\");\n// logs -\u003e emitted data:  first emit\nbEmitter.emit(\"ping\", \"second emit\");\n// logs -\u003e emitted data:  second emit\n\nbEmitter.off(\"ping\", ping); // listener is removed\nbEmitter.emit(\"ping\", \"third emit\");\n// doesn't log anything as listener is removed\n\nfunction bufferdPing(data: string[]) {\n  console.log(\"buffered data: \", data);\n}\n// adding a buffered listener which will receive emissions in batch of 2\nbEmitter.on(\"ping\", bufferdPing, { buffered: true, bufferCapacity: 2 });\nbEmitter.emit(\"ping\", \"first emit\");\n// doesn't log anything\nbEmitter.emit(\"ping\", \"second emit\");\n// logs -\u003e buffered data:  ['first emit', 'second emit']\nbEmitter.emit(\"ping\", \"third emit\");\n// doesn't log anything\n\n// flushes any events in the buffer associated with provided listener\nbEmitter.flush(\"ping\", bufferdPing, { buffered: true, bufferCapacity: 2 });\n// logs -\u003e buffered data:  ['third emit']\n\nbEmitter.pause(true);\n// emissions after this, will be queued\n\nconsole.log(\"emission queued\");\n\nbEmitter.emit(\"ping\", \"1\");\nbEmitter.emit(\"ping\", \"2\");\nbEmitter.emit(\"ping\", \"3\");\n\nbEmitter.resume();\n// logs -\u003e buffered data: [\"1\", \"2\"]\n\nconsole.log(\"emission dequeued\");\n\nbEmitter.emit(\"ping\", \"4\");\n// logs -\u003e buffered data: [\"3\", \"4\"]\n```\n\n**Demo**: https://stackblitz.com/edit/buffered-event-emitter-example-one\n\n### Usage in Node\n\nUsing esm\n\n```typescript\n// index.mjs\n\nimport { BufferedEventEmitter } from \"buffered-event-emitter\";\n\nconst bEmitter = new BufferedEventEmitter();\n```\n\nUsing CommonJs\n\n```typescript\n// index.js\n\nconst { BufferedEventEmitter } = require(\"buffered-event-emitter\");\n\nconst bEmitter = new BufferedEventEmitter();\n```\n\n### Usage in Browser\n\nUsing esm with a bundler\n\n```typescript\n// index.js\n\nimport { BufferedEventEmitter } from \"buffered-event-emitter\";\n\nconst bEmitter = new BufferedEventEmitter();\n```\n\nUsing via script tag\n\n```html\n\u003c!-- index.html --\u003e\n\n\u003c!-- For Dev Env --\u003e\n\u003cscript src=\"https://unpkg.com/buffered-event-emitter\"\u003e\u003c/script\u003e\n\n\u003c!-- For Production Env--\u003e\n\u003cscript src=\"https://unpkg.com/buffered-event-emitter/lib/bundle.umd.min.js\"\u003e\u003c/script\u003e\n```\n\n```typescript\n// index.js\nconst bEmitter = new BufferedEventEmitter();\n```\n\n## API\n\n### new BufferedEventEmitter(options?)\n\n```typescript\nconst bEmitter = new BufferedEventEmitter();\n```\n\nCreate a new instance of BufferedEventEmitter.\n\n#### `options?: InitOptions` \u003c!-- omit in toc --\u003e\n\nType: `object`\n\n```typescript\n{\n buffered?: boolean;\n bufferCapacity?: number;\n bufferInactivityTimeout?: number;\n logger?: Function;\n cache?: boolean;\n cacheCapacity?: number\n}\n```\n\nConfig options for instance of BufferedEventEmitter.\n\n#### `buffered?` \u003c!-- omit in toc --\u003e\n\nType: `boolean`\\\nDefault: `False`\n\nConfigure if event listeners registered on this instance will received buffered event data.\n\n#### `bufferCapacity?` \u003c!-- omit in toc --\u003e\n\nType: `number`\\\nDefault: `5`\n\nConfigure buffer capacity. Default capacity of 5 means event listener will receive event data every 5 emissions.\n****\n### `bufferInactivityTimeout?` \u003c!-- omit in toc --\u003e\n\nType: `number` \\\nDefault: `0` (ms)\n\nConfigure a default inactivity timeout for buffered listeners registered on this instance. If a buffered listener's bucket contains events and no new events are emitted for its event name within this duration, the listener will be automatically flushed with the current buffer content. A value of 0 disables the inactivity timeout at the instance level. This setting can be overridden per listener via its options.\n\n\n#### `logger` \u003c!-- omit in toc --\u003e\n\nType: `(type: \"emit\" | \"on\" | \"off\", eventName: string, eventData?: EventData | Listener) =\u003e void`  \nDefault: `logger` in utils https://github.com/33j33/buffered-event-emitter/blob/develop/src/utils.ts\n\nAdd a custom logger.\n\n#### `cache` \u003c!-- omit in toc --\u003e\n\nType: `boolean`\\\nDefault: `false`\n\nConfigure if event data should be cached. Stored data for an event can be retrieved though `getCache(eventName)`\n\n#### `cacheCapacity` \u003c!-- omit in toc --\u003e\n\nType: `number`\\\nDefault: `20`\n\nConfigure cache capacity. Data is stored and deleted in FIFO fashion. Once the cache is full, the first item in dequeued and another is enqueued.\n\n### emit(eventName, data?)\n\n```typescript\nemit(eventName: string, data?: EventData): boolean\n```\n\nSynchronously invokes each of the listeners registered for the event named `eventName` with `eventData` as argument, in the order they were registered.\n\nReturns `true` if any listener was invoked, `false` otherwise.\n\n#### Arguments \u003c!-- omit in toc --\u003e\n\n| Argument  | Type      | Required | Description                                           |\n| --------- | --------- | -------- | ----------------------------------------------------- |\n| eventName | string    | Yes      | Identifier for the event to be emitted                |\n| data      | EventData | No       | Argument to be passed to be listener when invoking it |\n\n### on(eventName, listener, options?)\n\n```typescript\non(eventName: string, listener: Listener,  options?: ListenerOptions): boolean\n```\n\nAdds an event listener for given `eventName` and `options`.\nIf the combination of `listener` and `options` is already present for the event, the `listener` is not added a second time.\n\nReturns `true` if listener was added `false` otherwise.\n\n#### Arguments \u003c!-- omit in toc --\u003e\n\n| Argument  | Type            | Required | Description                                                                                                          |\n| --------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------- |\n| eventName | string          | Yes      | Identifier for the event to be emitted                                                                               |\n| listener  | Listener        | Yes      | Callback that will be invoked each time event is emitted                                                             |\n| options   | ListenerOptions | No       | Config options for listener, eg `{ buffered: true, bufferCapacity: 2 }` creates buffered listener with capacity of 2 |\n\n### once(eventName, listener, options?)\n\n```typescript\nonce(eventName: string, listener: Listener,  options?: ListenerOptions): boolean\n```\n\nAdds a one-time event `listener` for given `eventName` and `options`.\nIf the combination of `listener` and `options` is already present for the event, the listener is not added a second time.\nThe first time event is triggered, this listener is invoked and then removed.\n\nReturns `true` if listener was added `false` otherwise.\n\n#### Arguments \u003c!-- omit in toc --\u003e\n\n| Argument  | Type            | Required | Description                                                                                                          |\n| --------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------- |\n| eventName | string          | Yes      | Identifier for the event to be emitted                                                                               |\n| listener  | Listener        | Yes      | Callback that will be invoked each time event is emitted                                                             |\n| options   | ListenerOptions | No       | Config options for listener, eg `{ buffered: true, bufferCapacity: 2 }` creates buffered listener with capacity of 2 |\n\n### off(eventName, listener, options?)\n\n```typescript\noff(eventName: string, listener: Listener,  options?: ListenerOptions): boolean\n```\n\nRemoves an event listener previously registered with `on()` or `addListener()`.\nThe event listener to be removed is identified using a combination of the `eventName`, the event `listener` function itself, and provided `options`.\n\nReturns `true` if listener was removed `false` otherwise.\n\n#### Arguments \u003c!-- omit in toc --\u003e\n\n| Argument  | Type            | Required | Description                            |\n| --------- | --------------- | -------- | -------------------------------------- |\n| eventName | string          | Yes      | Identifier for the event to be emitted |\n| listener  | Listener        | Yes      | Callback to be removed                 |\n| options   | ListenerOptions | No       | Config options for listener            |\n\n### flush(eventName, listener?, options?)\n\n```typescript\nflush(eventName: string): boolean;\nflush(eventName: string, listener: Listener, options: ListenerOptions): boolean;\n```\n\nFlush all buffered events for listeners for given event name if only `eventName` is provided, else buffered events for given combination of `eventName`, `listener` and `options` are flushed.\nReturns `true` if any events were flushed (emitted), `false` otherwise.\n\n#### Arguments \u003c!-- omit in toc --\u003e\n\n| Argument  | Type            | Required | Description                                                 |\n| --------- | --------------- | -------- | ----------------------------------------------------------- |\n| eventName | string          | Yes      | Identifier for the event to be emitted                      |\n| listener  | Listener        | No       | Callback which was registered earlier                       |\n| options   | ListenerOptions | No       | Config options which were passed while registering callback |\n\n### new EventController()\n\n```typescript\nconst control = new EventController();\n```\n\nType: `object`\n\n```typescript\nclass EventController {\n  public flush: () =\u003e void;\n  public off: () =\u003e void;\n}\n```\n\nCreates an instance of EventController which when provided while registering event listeners can be used to control multiple event listeners at once.\n\n```typescript\nconst listener = (arg: number) =\u003e {\n  console.log(arg);\n};\nconst control = new EventController();\nemitter.on(\"foo\", listener, { control });\nemitter.on(\"bar\", listener, { control });\nemitter.on(\"baz\", listener, { control });\n\nemitter.emit(\"foo\", 10); // 10\ncontrol.off(); // removes all the listeners at once\n\n// logs nothing\nemitter.emit(\"foo\", 20);\nemitter.emit(\"bar\", 20);\nemitter.emit(\"baz\", 20);\n```\n\n### pause({queueEmissions?, emissionInterval?, eventName?})\n\n```typescript\npause({queueEmissions?: boolean = true, emissionInterval?: number = 0, eventName?: string}): void\n```\n\nPause event emissions for all or given event. Any subsequent event emissions will be swallowed or queued and\ntheir respective listeners will not be invoked until `resume()` is called. If event name is provided, only the particular event is paused.\n\n| Argument         | Type    | Required | Description                                                                                                                     |\n| ---------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| queueEmissions   | boolean | No       | if true, subsequent event emissions will be queued else swallowed and the corresponding listeners not invoked.                  |\n| emissionInterval | number  | No       | interval for dequeueing queued events. if interval is 0, the events are dequeued synchronously else asynchronously but in order |\n| eventName        | string  | No       | name for the event to be paused                                                                                                 |\n\n### resume(eventName?)\n\n```typescript\nresume(eventName?: string): Promise\u003cvoid\u003e | void\n```\n\nResumes event emission for all events or provided event.\nEmits event asynchronously and returns a Promise if value of emission interval was greater than 0 when event emission was paused using `pause()` or else emits event synchronously. If eventName is provided resumes event emission for that particular event only.\n\n### enableDebug({ emit?, on?, off?})\n\n```typescript\nstatic enableDebug({ emit?: boolean; on?: boolean; off?: boolean })\n```\n\nEnables debugging for all instances of the event emitter through the `logger` function.  \nDepending on what actions are `true` in opts, logging is enabled for that action.  \nEg, `{ emit: true}` enables debuggin for all `emit` actions.\n\nExample:\n\n```typescript\nconst bEmitter = new BufferedEventEmitter();\nBufferedEventEmitter.enableDebug({ emit: true, on: true, off: true });\n\nfunction ping(data: string) {\n  // ...\n}\n\nbEmitter.on(\"ping\", ping);\nbEmitter.emit(\"ping\", \"first emit\");\nbEmitter.emit(\"ping\", \"second emit\");\nbEmitter.off(\"ping\", ping);\nbEmitter.emit(\"ping\", \"third emit\");\n\n// Logged data\n/**\n[Event Type: on | Event Name: ping | 22:23:23.801]\n    [Event Data: function ping(data) {    // ...}}]\n\n[Event Type: emit | Event Name: ping | 22:23:23.802]\n     [Event Data: \"first emit\"}]\n\n[Event Type: emit | Event Name: ping | 22:23:23.803]\n     [Event Data: \"second emit\"}]\n\n[Event Type: off | Event Name: ping | 22:23:23.803]\n     [Event Data: function ping(data) {    // ...}}]\n*/\n```\n\n### Types\n\n1. ListenerOptions\n\n```typescript\ntype ListenerOptions = {\n  buffered?: boolean;\n  bufferCapacity?: number;\n  bufferInactivityTimeout?: number;\n  control?: EventController;\n};\n```\n\n2. InitOptions\n\n```typescript\ntype InitOptions = {\n  buffered?: boolean; // false\n  bufferCapacity?: number; // 5\n  bufferInactivityTimeout?: number;\n  logger?: (type: \"emit\" | \"on\" | \"off\", eventName: string, eventData?: any) =\u003e void;\n  cache?: boolean; // false\n  cacheCapacity?: number; // 20\n};\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F33j33%2Fbuffered-event-emitter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F33j33%2Fbuffered-event-emitter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F33j33%2Fbuffered-event-emitter/lists"}