{"id":16255288,"url":"https://github.com/qubyte/vertebrate-event-emitter","last_synced_at":"2025-03-19T21:30:40.613Z","repository":{"id":44778675,"uuid":"52604504","full_name":"qubyte/vertebrate-event-emitter","owner":"qubyte","description":"An event emitter implementation robust against memory leaks.","archived":false,"fork":false,"pushed_at":"2022-01-25T11:28:39.000Z","size":329,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-28T23:21:16.782Z","etag":null,"topics":["es2015-modules","eventemitter","javascript","memory-leak","umd"],"latest_commit_sha":null,"homepage":null,"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/qubyte.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-26T12:57:01.000Z","updated_at":"2023-08-23T12:57:33.000Z","dependencies_parsed_at":"2022-09-05T02:20:17.925Z","dependency_job_id":null,"html_url":"https://github.com/qubyte/vertebrate-event-emitter","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qubyte%2Fvertebrate-event-emitter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qubyte%2Fvertebrate-event-emitter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qubyte%2Fvertebrate-event-emitter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qubyte%2Fvertebrate-event-emitter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qubyte","download_url":"https://codeload.github.com/qubyte/vertebrate-event-emitter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244056406,"owners_count":20390719,"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","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":["es2015-modules","eventemitter","javascript","memory-leak","umd"],"created_at":"2024-10-10T15:29:19.805Z","updated_at":"2025-03-19T21:30:40.278Z","avatar_url":"https://github.com/qubyte.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Vertebrate event emitter\n\nThis repository contains an implementation of an event emitter. Working with\nemitters can be frustrating. These frustrations led me to make an ES2015 based\nimplementation contained in this repository.\n\nKey features:\n\n - Based on `WeakMap` so you don't have to unregister callbacks when you drop\n   references to an emitter.\n - Unregister a callback using a reference (like `setTimeout`).\n - Give a registered callback a call count to unregister itself.\n\n[See below](#problems-with-existing-emitters) for why these are important.\n\nThis library comes with both UMD and ES2015 versions. If you're using\n[rollup](http://rollupjs.org/), it'll use the ES2015 version. Node will use\nthe UMD version automatically. Since this library provides UMD and ES2015\nversions, it's supported by every major module system (or no module system at\nall). It has no production dependencies, making it easy to include too!\n\n## API\n\n### Class `EventEmitter`\n\nThe `EventEmitter` is used to construct new emitter objects. It takes\nno arguments.\n\n```javascript\nconst emitter = new EventEmitter();\n```\n\n### `reference = emitter.on(name, callback, count = Infinity)`\n\nAdd a listener function `callback` to the emitter for the given `name`. `name`\nmust be a string. `count` is the number of times the event can be called before\nthe listener is automatically unregistered. `count` defaults to `Infinity` when\nnot given. When given it must be a positive integer greater than `1`, or\n`Infinity`.\n\nA `reference` object is returned, which may later be used to unregister the\nlistener.\n\n```javascript\n// Callback called every time 'event-name' triggered.\nemitter.on('event-name', callback);\n\n// Callback each time 'event-name' triggered, unregistering after 10 calls.\nemitter.on('event-name', callback, 10);\n```\n\nThe count parameter can be used to simulate a Node.js style `once` method.\n\n### `emitter.off(reference)`\n\nUnregister an event listener using the `reference` object returned by\n`emitter.on`.\n\n```javascript\n// The on method returns a reference object.\nconst ref = emitter.on('event-name', callback);\n\n// Use the off method to unregister the callback.\nemitter.off(ref);\n```\n\n### `emitter.allOff(name = undefined)`\n\nWhen called with a name string, all events for that name are removed from the\nemitter. When called without a name string, all events for all names are\nremoved.\n\n### `emitter.trigger(name, ...args)`\n\nTrigger all handlers for the given name with the remaining arguments `args`. The\ncallbacks are called with the emitter as `this`.\n\n```javascript\nfunction testCallback(a, b, c) {\n  console.log(a, b, c);\n}\n\nemitter.on('some-event', testCallback);\n\nemitter.trigger('some-event', 1, 2, 3) // logs: 1, 2, 3\n```\n\n### `emitter.emit(name, ...args)`\n\nAlias for `emitter.trigger`.\n\n## Problems with existing emitters\n\n### Emitters make memory leaks too easy to create\n\nFor example, if you add an event listener to a Backbone event emitter using\n`on`, it will stay there until something removes it. Backbone tries to get\naround this with `listenTo`, which allows the emitter itself to unregister\nevents in batch. This is no fault of existing implementations. JavaScript itself\nmade it an impossible problem to solve until recently.\n\nLuckily, one of the earlier features of ES2015 to make it into browsers was\n`WeakMap`, which allows the garbage collector to clean up members when no other\nreferences to them remain. The Vertebrate event emitter uses these to avoid\nmemory leaks.\n\n### Most implementations are keyed on event name and a callback\n\nIn Node, you might have code like:\n\n```javascript\nimport EventEmitter from 'events';\n\nconst emitter = new EventEmitter();\n\nfunction testCallback() {\n  console.log('Hello, world!');\n}\n\nemitter.on('test', testCallback); // Add a listener to the 'test' event.\n\nemitter.removeListener('test', testCallback); // Remove the listener.\n```\n\nThat looks fine, but what happens when you add the same callback for an event\ntwice? Does the callback get called twice per emission, or just once? If twice,\nwhat happens when you remove the listener? Does it remove both or just one?\n\nThis ambiguity bothers me.\n\nWhen a Vertebrate emitter has a listener registered for an event, it returns a\nreference object, a lot like `setTimeout` does. Unregistering the event is done\nusing this reference object:\n\n```javascript\nimport EventEmitter from 'vertebrate-event-emitter';\n\nconst emitter = new EventEmitter();\n\nfunction testCallback() {\n  console.log('Hello, world!');\n}\n\nconst ref = emitter.on('test', testCallback); // Add a listener.\n\nemitter.off(ref); // Remove the listener. No need to use the event name.\n```\n\nYou get a fresh reference object each time a listener is registered, so the\nambiguity never arises.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqubyte%2Fvertebrate-event-emitter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqubyte%2Fvertebrate-event-emitter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqubyte%2Fvertebrate-event-emitter/lists"}