{"_id":"@6pm/emit","_rev":"3-6ddfa7ddd0bace826b8e026f17cba97d","name":"@6pm/emit","description":"Screaming fast event emitter, with Symbol support","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@6pm/emit","version":"1.0.0","author":{"name":"James Andrews","email":"jka6510@gmail.com"},"description":"Screaming fast event emitter, with Symbol support","keywords":["event","emitter"],"scripts":{"test":"mocha --require babel-core/register test/**/*.spec.js","cover":"babel-node ./node_modules/.bin/babel-istanbul cover ./node_modules/.bin/_mocha -- test/**/*.spec.js","coveralls":"babel-node  ./node_modules/.bin/babel-istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","prepublish":"grunt build"},"main":"dist/emit.js","engines":{"node":">=4"},"devDependencies":{"babel-cli":"^6.16.0","babel-core":"^6.17.0","babel-istanbul":"^0.11.0","babel-plugin-external-helpers":"^6.8.0","babel-plugin-transform-es2015-modules-umd":"^6.12.0","coveralls":"^2.11.14","grunt":"^1.0.1","grunt-babel":"^6.0.0","grunt-contrib-watch":"^1.0.0","mocha":"^2.5.3","should":"^10.0.0","systemjs":"^0.19.29"},"directories":{"test":"test"},"babel":{"sourceMaps":"both","moduleId":"@6pm/emit","presets":[],"plugins":[["babel-plugin-transform-es2015-modules-umd",{"exactGlobals":true,"globals":{"@6pm/emit":"sixpm.emit"}}]]},"repository":{"type":"git","url":"https://www.github.com/6pm-js/emit.git"},"license":"MIT","gitHead":"b82020fc2f31e8ff07e4b884f9add8a303668607","_id":"@6pm/emit@1.0.0","_shasum":"c0be69e18aebf3facebe418647dee5b820443693","_from":".","_npmVersion":"3.10.8","_nodeVersion":"6.8.1","_npmUser":{"name":"6pm","email":"jka6510@gmail.com"},"dist":{"shasum":"c0be69e18aebf3facebe418647dee5b820443693","tarball":"https://registry.npmjs.org/@6pm/emit/-/emit-1.0.0.tgz","integrity":"sha512-DqrTazY/jZTKTgnrzMwwbesQTmPYQROt9bQ4S/tdMKl3g61aV6TfZgeHbNY7FY+N6ubS0DwP/Tgx5qkxJmdhlQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAhP+07C52Y4HQ7ZIV09tUe+kg0CIQe7oH07dDDBkvGMAiEAqS2ss2WSAjLdWg1jA8amGhizg9SNYxWqYJmc7PahKqM="}]},"maintainers":[{"name":"6pm","email":"jka6510@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/emit-1.0.0.tgz_1476902475727_0.2930380303878337"}}},"readme":"# 6pm/emit\r\n\r\n[![Version npm](https://img.shields.io/npm/v/@6pm/emit.svg)](https://www.npmjs.com/package/@6pm/emit) [![Build Status](https://img.shields.io/travis/6pm-js/emit/master.svg)](https://travis-ci.org/6pm-js/emit) [![Coverage Status](https://img.shields.io/coveralls/6pm-js/emit/master.svg)](https://coveralls.io/github/6pm-js/emit?branch=master)\r\n\r\nA zero dependency event emitter with lazy initialisation, zero memory and cpu\r\ninitial state, and full support for `Symbol` event types!\r\n\r\n\r\n\r\n\r\n## Installation\r\n\r\nAdd `@6pm/emit` to your project via npm.\r\n\r\n```sh\r\n$ npm install @6pm/emit --save\r\n```\r\n\r\n\r\n\r\n\r\n## Testing\r\n\r\nFirst grab a local clone of the github repo.\r\n\r\n```sh\r\n$ git clone https://github.com/6pm-js/emit.git\r\n$ cd emit\r\n```\r\n\r\nThe run the test suite:\r\n```sh\r\n$ npm test\r\n```\r\n\r\nOr use istanbul to produce a coverage report.\r\n\r\n```sh\r\n$ npm run cover\r\n```\r\n\r\n\r\n\r\n\r\n## A note on ES2015\r\n\r\n`@6pm/emit` is written using ES2015 features, and as such is directly compatible\r\nonly with Node versions >= 4.0.0, or recent evergreen browsers.\r\n\r\nIn theory, [Babel](https://babeljs.io/) or\r\n[Traceur](https://github.com/google/traceur-compile) could be used to\r\ntranspile for compatibility with considerably older JavaScript engines - if\r\nrequired.\r\n\r\nThe `@6pm/emit` module is also exposed via a ES2015 module, though the\r\nNPM package includes a UMD wrapped build in [dist/emit.js](./dist/emit.js),\r\nsuitable for inclusion in evergreen browsers, or directly accessing via\r\n`require` in Node.\r\n\r\nWhen using the UMD wrapped build directly in a web browser, the `Emit` class is\r\nexposed via the global `sixpm.emit.Emit`.\r\n\r\n\r\n\r\n\r\n## Usage\r\n\r\nMostly compatible with the core [NodeJS](https://nodejs.org/)\r\n[EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter),\r\nexcept:\r\n- addition of explicit context extensions, as defined by\r\n[eventemitter3](https://github.com/primus/eventemitter3)\r\n- removal of the 'uncaught `error` event throws' behaviour -\r\n\tthis is very counterintuitive - throw or emit, pick one, or *explicitly* do both.\r\n- removal of the expensive and pointless `newListener` and `removeListener` events.\r\n- Total ignorance of the max listeners setting and its very arbitrary warning.\r\n\r\nTo turn a class into an event emitter, there are two primary approaches:\r\n- by extension\r\n- by prototypical enhancement\r\n\r\n\r\n\r\n\r\n### By extension\r\n\r\nExtending the `Emit` class provides event emitter capabilities to the sub class.\r\n\r\n```js\r\nimport { Emit } from '@6pm/emit';\r\n\r\nclass SomeNewEmitter extends Emit {}\r\n\r\nlet instance\t= new SomeNewEmitter(),\r\n\tEVENT\t\t= Symbol('my.event');\r\n\r\n\r\ninstance.on(EVENT, () => { /* Do some work. */ });\r\n\r\ninstance.emit(EVENT, 1, 2, 3);\r\n```\r\n\r\n\r\n\r\n\r\n### By prototypical enhancement\r\n\r\nThe static `Emit.assign()` method assigns event emitter capabilities to the\r\ntarget object, which can be a static object, or a class prototype.\r\n\r\nBecause `6pm/emit` is initially stateless, no constructor overloading is\r\nrequired - `assign`ing Just Works™.\r\n\r\n```js\r\nimport { Emit as EventEmitter } from '@6pm/emit';\r\n\r\nclass SomeNewEmitter {\r\n\r\n\tconstructor() {\r\n\t\t// Note: no Emit based custom construction required.\r\n\t}\r\n}\r\n\r\nEventEmitter.assign(SomeNewEmitter.prototype);\r\n\r\nlet instance = new SomeNewEmitter(),\r\n\r\ninstance.on('some-event', () => { /* Do some work. */ });\r\n\r\ninstance.emit('some-event', result, false);\r\n```\r\n\r\n\r\n\r\n\r\n### Context enhancement\r\n\r\nThe following methods support a `context` being passed as an optional third\r\nargument, as a shortcut to avoid the overhead of `bind`ing a function to a\r\ncontext - an idea brazenly stolen from [eventemitter3](https://github.com/primus/eventemitter3).\r\n\r\n- `on`\r\n- `once`\r\n- `off`\r\n- `addListener`\r\n- `removeListener`\r\n\r\nSo, the following:\r\n\r\n```js\r\nsomeEmitter.on('event', callback, context);\r\n```\r\n\r\nis equivalent to, but considerably faster than:\r\n\r\n```js\r\nsomeEmitter.on('event', callback.bind(context));\r\n```\r\n\r\n\r\n\r\n\r\n## Design\r\n\r\n`@6pm/emit` is designed to address a very common design pattern in JavaScript.\r\n\r\nNamely, that event emission, and consumption are notably disjoint - libraries\r\ntypically emit many events, in order to expose complete lifecycles of managed\r\ninformation, but applications rarely consume them all - instead cherry picking a\r\nnecessary few as required.\r\n\r\n\r\n\r\n### Zero initial state\r\n\r\nThis module assumes no initial event state for any given event emitter, instead\r\naugmenting emitters only when listeners are registered for the first time,\r\nwith a 'fast path' that can make safe assumptions about hidden emitter state.\r\n\r\nThis means that there is no cpu overhead, or space requirements for event\r\nemitters, unless an application actually *listens* to them.\r\n\r\nThe trade off is that the augmented 'Fast path' methods require additional\r\nspace once listeners are registered - but for applications where many objects\r\nexpose event emitter interfaces, but few are used, this has a significant impact\r\non resource usage, and initialisation performance.\r\n\r\n\r\n\r\n\r\n### Encapsulated internals\r\n\r\nAll emitter state is hidden via ES2015 `Symbol`s, to prevent clashes, and\r\nprovide a degree of encapsulation in the design - though obviously not a perfect\r\napproach to preventing information leakage\r\n([getOwnPropertySymbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols) allows peering behind the veil)\r\n- this is generally safer than using named properties.\r\n\r\n\r\n\r\n\r\n### Symbol support\r\n\r\n`Symbol`s as event types are supported, and explicitly tested for, throughout\r\nthe module - as a matter of personal preference the effective separation /\r\nnamespacing and readability of `Symbol`s as events seems like a great approach.\r\n\r\nEvent production:\r\n\r\n```js\r\nimport { Emit } from '@6pm/emit';\r\n\r\nconst START = Symbol('someclass.start.event');\r\n\r\nexport class SomeClass {\r\n\r\n\tstart() {\r\n\t\tthis.emit(START);\r\n\t}\r\n\r\n}\r\n\r\nSomeClass.START = START;\r\n```\r\n\r\nEvent consumption:\r\n\r\n```js\r\nimport { SomeClass } from 'someclass.js';\r\n\r\nlet instance = SomeClass();\r\n\r\n// No potential for event name collision, elegant reference to source of event.\r\ninstance.on(SomeClass.START, () => { /* ... */ });\r\n```\r\n\r\n\r\n\r\n\r\n### Performance\r\n\r\nThe primary purpose of this module is to provide a (mostly) Node compatible\r\nAPI, to enforce zero initial state for unsubscribed emitters, to ensure strong\r\n`Symbol` support (due to mixed experiences in alternative libraries), and to use\r\na clean ES2015 code style.\r\n\r\nPerformance optimisation is a secondary concern, though by folding in the\r\nlessons learned by the sterling work of the [eventemitter3](https://github.com/primus/eventemitter3)\r\nteam, and then continuing to cut any excesses found, this implementation has\r\nbecome exceptionally efficient - microbenchmarks are a fairly poor measure of\r\nreal world performance - but if desired, it is fairly trivial to add `@6pm/emit`\r\nto eventemitter3's benchmark suite to asses raw overheads - and\r\n[the results](https://gist.github.com/6pm-js/781bc511d98454603f192ff16235e071)\r\n(to be consumed with a suitable serving of salt) show `@6pm/emit` as having no\r\nparticular weaknesses, and achieving the highest performance in around half of\r\nthe tests.\r\n\r\n> TODO: Add performance testing and resource monitoring tooling to allow\r\n> comprehensive testing of this *in the wild*.\r\n\r\n\r\n\r\n\r\n## Contributing\r\n\r\nAll comments, criticisms, PRs, and Issues welcome!\r\n\r\n\r\n\r\n\r\n## License\r\n\r\nRelease under the [MIT license](LICENSE)\r\n","maintainers":[{"name":"6pm","email":"jka6510@gmail.com"}],"time":{"modified":"2022-06-12T14:11:53.716Z","created":"2016-10-19T18:41:16.346Z","1.0.0":"2016-10-19T18:41:16.346Z"},"keywords":["event","emitter"],"repository":{"type":"git","url":"https://www.github.com/6pm-js/emit.git"},"author":{"name":"James Andrews","email":"jka6510@gmail.com"},"license":"MIT","readmeFilename":"README.md"}