From 2e332e10d9651df965c0d1ac600591248b31027f Mon Sep 17 00:00:00 2001 From: Lilian Saget-Lethias Date: Fri, 8 Jul 2016 15:36:20 +0200 Subject: [PATCH] Event Emitter project ! --- .bowerrc | 4 + .editorconfig | 23 +++++ .gitignore | 115 ++++++++++++++++++++++ .jscsrc | 6 ++ .jshintrc | 13 +++ .npmignore | 120 +++++++++++++++++++++++ .npmrc | 1 + LICENSE | 13 +++ README.md | 46 +++++++++ bin/EventEmitter.browser.js | 189 ++++++++++++++++++++++++++++++++++++ bin/EventEmitter.node.js | 3 + bower.json | 26 +++++ dist_node/EventEmitter.js | 131 +++++++++++++++++++++++++ gulpfile.js | 42 ++++++++ package.json | 45 +++++++++ src/EventEmitter.js | 188 +++++++++++++++++++++++++++++++++++ test/test.js | 130 +++++++++++++++++++++++++ 17 files changed, 1095 insertions(+) create mode 100644 .bowerrc create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .jscsrc create mode 100644 .jshintrc create mode 100644 .npmignore create mode 100644 .npmrc create mode 100644 LICENSE create mode 100644 README.md create mode 100644 bin/EventEmitter.browser.js create mode 100644 bin/EventEmitter.node.js create mode 100644 bower.json create mode 100644 dist_node/EventEmitter.js create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 src/EventEmitter.js create mode 100644 test/test.js diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..c88f1fd --- /dev/null +++ b/.bowerrc @@ -0,0 +1,4 @@ +{ + "registry": "https://bower.herokuapp.com" + +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1a0a316 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[*.json] +indent_size = 2 +insert_final_newline = false + +[src/**/*] +trim_trailing_whitespace = false + +[.npmrc] +insert_final_newline = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d6dcc2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,115 @@ +# Created by .ignore support plugin (hsz.mobi) +### OSX template +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml + +# Sensitive or high-churn files: +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/libraries + +# Mongo Explorer plugin: +.idea/mongoSettings.xml +.idea/ +.idea/* + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Node template +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +/.idea/ +/bower_components/ diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..f8bf9ba --- /dev/null +++ b/.jscsrc @@ -0,0 +1,6 @@ +{ + "requireCamelCaseOrUpperCaseIdentifiers": true, + "requireCapitalizedConstructors": true, + "requireParenthesesAroundIIFE": true, + "validateQuoteMarks": "'" +} diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..9797d31 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,13 @@ +{ + "bitwise": true, + "browser": true, + "curly": true, + "eqeqeq": true, + "esnext": true, + "latedef": true, + "noarg": true, + "node": true, + "strict": true, + "undef": true, + "unused": true +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..7f1e1f9 --- /dev/null +++ b/.npmignore @@ -0,0 +1,120 @@ +# Created by .ignore support plugin (hsz.mobi) +### OSX template +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml + +# Sensitive or high-churn files: +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/libraries + +# Mongo Explorer plugin: +.idea/mongoSettings.xml +.idea/ +.idea/* + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Node template +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +/.idea/ +/bower_components/ + +dist_browser/ +bower.json +.bowerrc +bin/EventEmitter.browser.js diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..e1531a3 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry = https://registry.npmjs.org \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94c36d0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2016, Lilian Saget-Lethias + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4c6f4d1 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# eventemitter-promise + +Event Emitter with lazy promise ! (see http://github.com/bios21/superlazypromise) + +## Installation + +Then install it via npm: + +``` bash +$ npm install --save eventemitter-promise +``` + +Or via bower: + +``` bash +$ bower install --save eventemitter-promise +``` + +## Example Usage + +Each listener are stored to be fired later on a `SuperLazyPromise` + +| emit\on | event | event.* | event.context | event.context! | +|:--------------:|:-----:|:-------:|:-------------:|:--------------:| +| event | ✓ | ✓ | ✓ | ✓ | +| event.context | ✓ | | ✓ | ✓ | +| event.context! | | | ✓ | ✓ | + +**!** : Firing an event on strict context (`event.context!`) is not yet implemented. + +``` js +const EventEmitter = require('eventemitter-promise'); + +class Clazz extends EventEmitter { + emit() { + } + on() { + } +} +``` + + +License +---- + +ISC License. See the `LICENSE` file. diff --git a/bin/EventEmitter.browser.js b/bin/EventEmitter.browser.js new file mode 100644 index 0000000..3713aee --- /dev/null +++ b/bin/EventEmitter.browser.js @@ -0,0 +1,189 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var _module = null, + _exports = null; +if (module && module.exports) { + _exports = module.exports; + _module = { + SuperLazyPromise: require('superlazypromise').SuperLazyPromise + }; +} else { + _exports = window; + _module = _exports; +} + +(function (module, exports) { + var SuperLazyPromise = module.SuperLazyPromise; + + var EMPTY_FN = function EMPTY_FN() {}, + NS_SEPARATOR = '.'; + + var EventEmitter = function () { + function EventEmitter() { + _classCallCheck(this, EventEmitter); + + this._promises = new Map(); + } + + _createClass(EventEmitter, [{ + key: 'on', + value: function on(event) { + var SLP = this._promises.get(event), + hasContext = event.includes(NS_SEPARATOR), + splitEvent = event.split(NS_SEPARATOR), + promiseMainEvent = this._promises.get(splitEvent[0]); + + if (hasContext) { + if (SLP) { + if (!promiseMainEvent) { + promiseMainEvent = new SuperLazyPromise(SLP.fn); + promiseMainEvent.updatePromise(SLP.promise); + this._promises.set(splitEvent[0], promiseMainEvent); + } + } else { + if (promiseMainEvent) { + SLP = new SuperLazyPromise(promiseMainEvent.fn); + SLP.updatePromise(promiseMainEvent.promise); + this._promises.set(event, SLP); + } else { + this._promises.set(splitEvent[0], new SuperLazyPromise(EMPTY_FN)); + this._promises.set(event, new SuperLazyPromise(EMPTY_FN)); + } + } + } else { + if (!SLP) { + this._promises.set(event, new SuperLazyPromise(EMPTY_FN)); + } + } + return this._promises.get(event); + } + }, { + key: 'off', + value: function off(event) { + if (!event.includes(NS_SEPARATOR)) { + this._destroyPromise(event); + } else { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = this._promises[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var keyVal = _step.value; + + if (keyVal[0].split(NS_SEPARATOR)[0] === event) { + this._destroyPromise(keyVal[0]); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + } + }, { + key: '_destroyPromise', + value: function _destroyPromise(event) { + this._promises[event].kill(); + delete this._promises[event]; + } + }, { + key: 'emit', + value: function emit(event) { + for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + data[_key - 1] = arguments[_key]; + } + + var executor = function executor(ok, ko) { + return ok.apply(undefined, data); + }; + + var SLP = this._promises.get(event), + hasContext = event.includes(NS_SEPARATOR), + splitEvent = event.split(NS_SEPARATOR), + promiseMainEvent = this._promises.get(splitEvent[0]); + + if (hasContext) { + if (SLP) { + SLP.awake(executor); + if (promiseMainEvent) { + promiseMainEvent.awake(executor); + } else { + promiseMainEvent = new SuperLazyPromise(EMPTY_FN); + promiseMainEvent.updatePromise(SLP.promise); + this._promises.set(splitEvent[0], promiseMainEvent); + } + } else { + if (promiseMainEvent) { + promiseMainEvent.awake(executor); + SLP = new SuperLazyPromise(EMPTY_FN); + SLP.updatePromise(promiseMainEvent.promise); + } else { + promiseMainEvent = new SuperLazyPromise(executor); + promiseMainEvent.awake(); + SLP = new SuperLazyPromise(EMPTY_FN); + SLP.updatePromise(promiseMainEvent.promise); + } + } + } else { + if (SLP) { + SLP.awake(executor); + } else { + SLP = new SuperLazyPromise(executor); + SLP.awake(); + this._promises.set(event, SLP); + } + + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = this._promises[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var keyVal = _step2.value; + + if (keyVal[0].includes(NS_SEPARATOR) && keyVal[0].split(NS_SEPARATOR)[0] === event) { + var subEvent = keyVal[0], + subPromise = this._promises.get(subEvent); + subPromise.updatePromise(SLP.promise); + subPromise.awake(); + } + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + } + } + }]); + + return EventEmitter; + }(); + + exports.EventEmitter = EventEmitter; +})(_module, _exports); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV2ZW50RW1pdHRlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6Ii4uL2Jpbi9FdmVudEVtaXR0ZXIuYnJvd3Nlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIF9tb2R1bGUgPSBudWxsLFxuICAgIF9leHBvcnRzID0gbnVsbDtcbmlmIChtb2R1bGUgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICBfZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzO1xuICAgIF9tb2R1bGUgPSB7XG4gICAgICAgIFN1cGVyTGF6eVByb21pc2U6IHJlcXVpcmUoJ3N1cGVybGF6eXByb21pc2UnKS5TdXBlckxhenlQcm9taXNlXG4gICAgfTtcbn0gZWxzZSB7XG4gICAgX2V4cG9ydHMgPSB3aW5kb3c7XG4gICAgX21vZHVsZSA9IF9leHBvcnRzO1xufVxuXG4oZnVuY3Rpb24gKG1vZHVsZSwgZXhwb3J0cykge1xuICAgIHZhciBTdXBlckxhenlQcm9taXNlID0gbW9kdWxlLlN1cGVyTGF6eVByb21pc2U7XG5cbiAgICB2YXIgRU1QVFlfRk4gPSBmdW5jdGlvbiBFTVBUWV9GTigpIHt9LFxuICAgICAgICBOU19TRVBBUkFUT1IgPSAnLic7XG5cbiAgICB2YXIgRXZlbnRFbWl0dGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gICAgICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRXZlbnRFbWl0dGVyKTtcblxuICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cblxuICAgICAgICBfY3JlYXRlQ2xhc3MoRXZlbnRFbWl0dGVyLCBbe1xuICAgICAgICAgICAga2V5OiAnb24nLFxuICAgICAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIG9uKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIFNMUCA9IHRoaXMuX3Byb21pc2VzLmdldChldmVudCksXG4gICAgICAgICAgICAgICAgICAgIGhhc0NvbnRleHQgPSBldmVudC5pbmNsdWRlcyhOU19TRVBBUkFUT1IpLFxuICAgICAgICAgICAgICAgICAgICBzcGxpdEV2ZW50ID0gZXZlbnQuc3BsaXQoTlNfU0VQQVJBVE9SKSxcbiAgICAgICAgICAgICAgICAgICAgcHJvbWlzZU1haW5FdmVudCA9IHRoaXMuX3Byb21pc2VzLmdldChzcGxpdEV2ZW50WzBdKTtcblxuICAgICAgICAgICAgICAgIGlmIChoYXNDb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChTTFApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcHJvbWlzZU1haW5FdmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShTTFAuZm4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQudXBkYXRlUHJvbWlzZShTTFAucHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMuc2V0KHNwbGl0RXZlbnRbMF0sIHByb21pc2VNYWluRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb21pc2VNYWluRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTTFAgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShwcm9taXNlTWFpbkV2ZW50LmZuKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTTFAudXBkYXRlUHJvbWlzZShwcm9taXNlTWFpbkV2ZW50LnByb21pc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb21pc2VzLnNldChldmVudCwgU0xQKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMuc2V0KHNwbGl0RXZlbnRbMF0sIG5ldyBTdXBlckxhenlQcm9taXNlKEVNUFRZX0ZOKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMuc2V0KGV2ZW50LCBuZXcgU3VwZXJMYXp5UHJvbWlzZShFTVBUWV9GTikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFTTFApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb21pc2VzLnNldChldmVudCwgbmV3IFN1cGVyTGF6eVByb21pc2UoRU1QVFlfRk4pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcHJvbWlzZXMuZ2V0KGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnb2ZmJyxcbiAgICAgICAgICAgIHZhbHVlOiBmdW5jdGlvbiBvZmYoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWV2ZW50LmluY2x1ZGVzKE5TX1NFUEFSQVRPUikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGVzdHJveVByb21pc2UoZXZlbnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIF9kaWRJdGVyYXRvckVycm9yID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfaXRlcmF0b3JFcnJvciA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2l0ZXJhdG9yID0gdGhpcy5fcHJvbWlzZXNbU3ltYm9sLml0ZXJhdG9yXSgpLCBfc3RlcDsgIShfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uID0gKF9zdGVwID0gX2l0ZXJhdG9yLm5leHQoKSkuZG9uZSk7IF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24gPSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleVZhbCA9IF9zdGVwLnZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleVZhbFswXS5zcGxpdChOU19TRVBBUkFUT1IpWzBdID09PSBldmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kZXN0cm95UHJvbWlzZShrZXlWYWxbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfZGlkSXRlcmF0b3JFcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBfaXRlcmF0b3JFcnJvciA9IGVycjtcbiAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uICYmIF9pdGVyYXRvci5yZXR1cm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2l0ZXJhdG9yLnJldHVybigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9kaWRJdGVyYXRvckVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IF9pdGVyYXRvckVycm9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5OiAnX2Rlc3Ryb3lQcm9taXNlJyxcbiAgICAgICAgICAgIHZhbHVlOiBmdW5jdGlvbiBfZGVzdHJveVByb21pc2UoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wcm9taXNlc1tldmVudF0ua2lsbCgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9wcm9taXNlc1tldmVudF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGtleTogJ2VtaXQnLFxuICAgICAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGVtaXQoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgZGF0YSA9IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YVtfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGV4ZWN1dG9yID0gZnVuY3Rpb24gZXhlY3V0b3Iob2ssIGtvKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvay5hcHBseSh1bmRlZmluZWQsIGRhdGEpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICB2YXIgU0xQID0gdGhpcy5fcHJvbWlzZXMuZ2V0KGV2ZW50KSxcbiAgICAgICAgICAgICAgICAgICAgaGFzQ29udGV4dCA9IGV2ZW50LmluY2x1ZGVzKE5TX1NFUEFSQVRPUiksXG4gICAgICAgICAgICAgICAgICAgIHNwbGl0RXZlbnQgPSBldmVudC5zcGxpdChOU19TRVBBUkFUT1IpLFxuICAgICAgICAgICAgICAgICAgICBwcm9taXNlTWFpbkV2ZW50ID0gdGhpcy5fcHJvbWlzZXMuZ2V0KHNwbGl0RXZlbnRbMF0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKGhhc0NvbnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFNMUCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgU0xQLmF3YWtlKGV4ZWN1dG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9taXNlTWFpbkV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZU1haW5FdmVudC5hd2FrZShleGVjdXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShFTVBUWV9GTik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZU1haW5FdmVudC51cGRhdGVQcm9taXNlKFNMUC5wcm9taXNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcm9taXNlcy5zZXQoc3BsaXRFdmVudFswXSwgcHJvbWlzZU1haW5FdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvbWlzZU1haW5FdmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQuYXdha2UoZXhlY3V0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNMUCA9IG5ldyBTdXBlckxhenlQcm9taXNlKEVNUFRZX0ZOKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTTFAudXBkYXRlUHJvbWlzZShwcm9taXNlTWFpbkV2ZW50LnByb21pc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlTWFpbkV2ZW50ID0gbmV3IFN1cGVyTGF6eVByb21pc2UoZXhlY3V0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQuYXdha2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTTFAgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShFTVBUWV9GTik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgU0xQLnVwZGF0ZVByb21pc2UocHJvbWlzZU1haW5FdmVudC5wcm9taXNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChTTFApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFNMUC5hd2FrZShleGVjdXRvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBTTFAgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShleGVjdXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBTTFAuYXdha2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb21pc2VzLnNldChldmVudCwgU0xQKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfZGlkSXRlcmF0b3JFcnJvcjIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIF9pdGVyYXRvckVycm9yMiA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2l0ZXJhdG9yMiA9IHRoaXMuX3Byb21pc2VzW1N5bWJvbC5pdGVyYXRvcl0oKSwgX3N0ZXAyOyAhKF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24yID0gKF9zdGVwMiA9IF9pdGVyYXRvcjIubmV4dCgpKS5kb25lKTsgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjIgPSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGtleVZhbCA9IF9zdGVwMi52YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrZXlWYWxbMF0uaW5jbHVkZXMoTlNfU0VQQVJBVE9SKSAmJiBrZXlWYWxbMF0uc3BsaXQoTlNfU0VQQVJBVE9SKVswXSA9PT0gZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN1YkV2ZW50ID0ga2V5VmFsWzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViUHJvbWlzZSA9IHRoaXMuX3Byb21pc2VzLmdldChzdWJFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YlByb21pc2UudXBkYXRlUHJvbWlzZShTTFAucHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YlByb21pc2UuYXdha2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2RpZEl0ZXJhdG9yRXJyb3IyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9pdGVyYXRvckVycm9yMiA9IGVycjtcbiAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMiAmJiBfaXRlcmF0b3IyLnJldHVybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfaXRlcmF0b3IyLnJldHVybigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9kaWRJdGVyYXRvckVycm9yMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBfaXRlcmF0b3JFcnJvcjI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XSk7XG5cbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9KCk7XG5cbiAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcbn0pKF9tb2R1bGUsIF9leHBvcnRzKTsiXSwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= diff --git a/bin/EventEmitter.node.js b/bin/EventEmitter.node.js new file mode 100644 index 0000000..3cba73c --- /dev/null +++ b/bin/EventEmitter.node.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('../dist_node/EventEmitter').EventEmitter; diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..8544c04 --- /dev/null +++ b/bower.json @@ -0,0 +1,26 @@ +{ + "name": "eventemitter-promise", + "description": "Event Emitter with lazy promise.", + "main": "bin/EventEmitter.browser.js", + "authors": [ + "Lilian Saget-Lethias (http://github.com/bios21)" + ], + "license": "ISC", + "keywords": [ + "event", + "eventemitter", + "lazy", + "promise", + "a+", + "then", + "thenable" + ], + "homepage": "https://github.com/bios21/eventemitter-promise#readme", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} diff --git a/dist_node/EventEmitter.js b/dist_node/EventEmitter.js new file mode 100644 index 0000000..75a6d6e --- /dev/null +++ b/dist_node/EventEmitter.js @@ -0,0 +1,131 @@ +'use strict'; + +var _module = null, + _exports = null; +if (module && module.exports) { + _exports = module.exports; + _module = { + SuperLazyPromise: require('superlazypromise').SuperLazyPromise + }; +} else { + _exports = window; + _module = _exports; +} + +((module, exports) => { + const SuperLazyPromise = module.SuperLazyPromise; + + const EMPTY_FN = function EMPTY_FN() {}, + NS_SEPARATOR = '.'; + + class EventEmitter { + constructor() { + this._promises = new Map(); + } + + on(event) { + let SLP = this._promises.get(event), + hasContext = event.includes(NS_SEPARATOR), + splitEvent = event.split(NS_SEPARATOR), + promiseMainEvent = this._promises.get(splitEvent[0]); + + if (hasContext) { + if (SLP) { + if (!promiseMainEvent) { + promiseMainEvent = new SuperLazyPromise(SLP.fn); + promiseMainEvent.updatePromise(SLP.promise); + this._promises.set(splitEvent[0], promiseMainEvent); + } + } else { + if (promiseMainEvent) { + SLP = new SuperLazyPromise(promiseMainEvent.fn); + SLP.updatePromise(promiseMainEvent.promise); + this._promises.set(event, SLP); + } else { + this._promises.set(splitEvent[0], new SuperLazyPromise(EMPTY_FN)); + this._promises.set(event, new SuperLazyPromise(EMPTY_FN)); + } + } + } else { + if (!SLP) { + this._promises.set(event, new SuperLazyPromise(EMPTY_FN)); + } + } + return this._promises.get(event); + } + + off(event) { + if (!event.includes(NS_SEPARATOR)) { + this._destroyPromise(event); + } else { + for (let keyVal of this._promises) { + if (keyVal[0].split(NS_SEPARATOR)[0] === event) { + this._destroyPromise(keyVal[0]); + } + } + } + } + + _destroyPromise(event) { + this._promises[event].kill(); + delete this._promises[event]; + } + + emit(event) { + for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + data[_key - 1] = arguments[_key]; + } + + const executor = (ok, ko) => ok.apply(undefined, data); + + let SLP = this._promises.get(event), + hasContext = event.includes(NS_SEPARATOR), + splitEvent = event.split(NS_SEPARATOR), + promiseMainEvent = this._promises.get(splitEvent[0]); + + if (hasContext) { + if (SLP) { + SLP.awake(executor); + if (promiseMainEvent) { + promiseMainEvent.awake(executor); + } else { + promiseMainEvent = new SuperLazyPromise(EMPTY_FN); + promiseMainEvent.updatePromise(SLP.promise); + this._promises.set(splitEvent[0], promiseMainEvent); + } + } else { + if (promiseMainEvent) { + promiseMainEvent.awake(executor); + SLP = new SuperLazyPromise(EMPTY_FN); + SLP.updatePromise(promiseMainEvent.promise); + } else { + promiseMainEvent = new SuperLazyPromise(executor); + promiseMainEvent.awake(); + SLP = new SuperLazyPromise(EMPTY_FN); + SLP.updatePromise(promiseMainEvent.promise); + } + } + } else { + if (SLP) { + SLP.awake(executor); + } else { + SLP = new SuperLazyPromise(executor); + SLP.awake(); + this._promises.set(event, SLP); + } + + for (let keyVal of this._promises) { + if (keyVal[0].includes(NS_SEPARATOR) && keyVal[0].split(NS_SEPARATOR)[0] === event) { + let subEvent = keyVal[0], + subPromise = this._promises.get(subEvent); + subPromise.updatePromise(SLP.promise); + subPromise.awake(); + } + } + } + } + } + + exports.EventEmitter = EventEmitter; +})(_module, _exports); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFdmVudEVtaXR0ZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX21vZHVsZSA9IG51bGwsXG4gICAgX2V4cG9ydHMgPSBudWxsO1xuaWYgKG1vZHVsZSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgIF9leHBvcnRzID0gbW9kdWxlLmV4cG9ydHM7XG4gICAgX21vZHVsZSA9IHtcbiAgICAgICAgU3VwZXJMYXp5UHJvbWlzZTogcmVxdWlyZSgnc3VwZXJsYXp5cHJvbWlzZScpLlN1cGVyTGF6eVByb21pc2VcbiAgICB9O1xufSBlbHNlIHtcbiAgICBfZXhwb3J0cyA9IHdpbmRvdztcbiAgICBfbW9kdWxlID0gX2V4cG9ydHM7XG59XG5cbigobW9kdWxlLCBleHBvcnRzKSA9PiB7XG4gICAgY29uc3QgU3VwZXJMYXp5UHJvbWlzZSA9IG1vZHVsZS5TdXBlckxhenlQcm9taXNlO1xuXG4gICAgY29uc3QgRU1QVFlfRk4gPSBmdW5jdGlvbiBFTVBUWV9GTigpIHt9LFxuICAgICAgICAgIE5TX1NFUEFSQVRPUiA9ICcuJztcblxuICAgIGNsYXNzIEV2ZW50RW1pdHRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cblxuICAgICAgICBvbihldmVudCkge1xuICAgICAgICAgICAgbGV0IFNMUCA9IHRoaXMuX3Byb21pc2VzLmdldChldmVudCksXG4gICAgICAgICAgICAgICAgaGFzQ29udGV4dCA9IGV2ZW50LmluY2x1ZGVzKE5TX1NFUEFSQVRPUiksXG4gICAgICAgICAgICAgICAgc3BsaXRFdmVudCA9IGV2ZW50LnNwbGl0KE5TX1NFUEFSQVRPUiksXG4gICAgICAgICAgICAgICAgcHJvbWlzZU1haW5FdmVudCA9IHRoaXMuX3Byb21pc2VzLmdldChzcGxpdEV2ZW50WzBdKTtcblxuICAgICAgICAgICAgaWYgKGhhc0NvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoU0xQKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghcHJvbWlzZU1haW5FdmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZU1haW5FdmVudCA9IG5ldyBTdXBlckxhenlQcm9taXNlKFNMUC5mbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlTWFpbkV2ZW50LnVwZGF0ZVByb21pc2UoU0xQLnByb21pc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMuc2V0KHNwbGl0RXZlbnRbMF0sIHByb21pc2VNYWluRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb21pc2VNYWluRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFNMUCA9IG5ldyBTdXBlckxhenlQcm9taXNlKHByb21pc2VNYWluRXZlbnQuZm4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgU0xQLnVwZGF0ZVByb21pc2UocHJvbWlzZU1haW5FdmVudC5wcm9taXNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb21pc2VzLnNldChldmVudCwgU0xQKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb21pc2VzLnNldChzcGxpdEV2ZW50WzBdLCBuZXcgU3VwZXJMYXp5UHJvbWlzZShFTVBUWV9GTikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMuc2V0KGV2ZW50LCBuZXcgU3VwZXJMYXp5UHJvbWlzZShFTVBUWV9GTikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoIVNMUCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcm9taXNlcy5zZXQoZXZlbnQsIG5ldyBTdXBlckxhenlQcm9taXNlKEVNUFRZX0ZOKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3Byb21pc2VzLmdldChldmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBvZmYoZXZlbnQpIHtcbiAgICAgICAgICAgIGlmICghZXZlbnQuaW5jbHVkZXMoTlNfU0VQQVJBVE9SKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lQcm9taXNlKGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQga2V5VmFsIG9mIHRoaXMuX3Byb21pc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXlWYWxbMF0uc3BsaXQoTlNfU0VQQVJBVE9SKVswXSA9PT0gZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lQcm9taXNlKGtleVZhbFswXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBfZGVzdHJveVByb21pc2UoZXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3Byb21pc2VzW2V2ZW50XS5raWxsKCk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fcHJvbWlzZXNbZXZlbnRdO1xuICAgICAgICB9XG5cbiAgICAgICAgZW1pdChldmVudCkge1xuICAgICAgICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGRhdGEgPSBBcnJheShfbGVuID4gMSA/IF9sZW4gLSAxIDogMCksIF9rZXkgPSAxOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICAgICAgICAgICAgZGF0YVtfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGV4ZWN1dG9yID0gKG9rLCBrbykgPT4gb2suYXBwbHkodW5kZWZpbmVkLCBkYXRhKTtcblxuICAgICAgICAgICAgbGV0IFNMUCA9IHRoaXMuX3Byb21pc2VzLmdldChldmVudCksXG4gICAgICAgICAgICAgICAgaGFzQ29udGV4dCA9IGV2ZW50LmluY2x1ZGVzKE5TX1NFUEFSQVRPUiksXG4gICAgICAgICAgICAgICAgc3BsaXRFdmVudCA9IGV2ZW50LnNwbGl0KE5TX1NFUEFSQVRPUiksXG4gICAgICAgICAgICAgICAgcHJvbWlzZU1haW5FdmVudCA9IHRoaXMuX3Byb21pc2VzLmdldChzcGxpdEV2ZW50WzBdKTtcblxuICAgICAgICAgICAgaWYgKGhhc0NvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoU0xQKSB7XG4gICAgICAgICAgICAgICAgICAgIFNMUC5hd2FrZShleGVjdXRvcik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9taXNlTWFpbkV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlTWFpbkV2ZW50LmF3YWtlKGV4ZWN1dG9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShFTVBUWV9GTik7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlTWFpbkV2ZW50LnVwZGF0ZVByb21pc2UoU0xQLnByb21pc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMuc2V0KHNwbGl0RXZlbnRbMF0sIHByb21pc2VNYWluRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb21pc2VNYWluRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQuYXdha2UoZXhlY3V0b3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgU0xQID0gbmV3IFN1cGVyTGF6eVByb21pc2UoRU1QVFlfRk4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgU0xQLnVwZGF0ZVByb21pc2UocHJvbWlzZU1haW5FdmVudC5wcm9taXNlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VNYWluRXZlbnQgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShleGVjdXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlTWFpbkV2ZW50LmF3YWtlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBTTFAgPSBuZXcgU3VwZXJMYXp5UHJvbWlzZShFTVBUWV9GTik7XG4gICAgICAgICAgICAgICAgICAgICAgICBTTFAudXBkYXRlUHJvbWlzZShwcm9taXNlTWFpbkV2ZW50LnByb21pc2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoU0xQKSB7XG4gICAgICAgICAgICAgICAgICAgIFNMUC5hd2FrZShleGVjdXRvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgU0xQID0gbmV3IFN1cGVyTGF6eVByb21pc2UoZXhlY3V0b3IpO1xuICAgICAgICAgICAgICAgICAgICBTTFAuYXdha2UoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvbWlzZXMuc2V0KGV2ZW50LCBTTFApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAobGV0IGtleVZhbCBvZiB0aGlzLl9wcm9taXNlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5VmFsWzBdLmluY2x1ZGVzKE5TX1NFUEFSQVRPUikgJiYga2V5VmFsWzBdLnNwbGl0KE5TX1NFUEFSQVRPUilbMF0gPT09IGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3ViRXZlbnQgPSBrZXlWYWxbMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViUHJvbWlzZSA9IHRoaXMuX3Byb21pc2VzLmdldChzdWJFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJQcm9taXNlLnVwZGF0ZVByb21pc2UoU0xQLnByb21pc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3ViUHJvbWlzZS5hd2FrZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG59KShfbW9kdWxlLCBfZXhwb3J0cyk7Il0sImZpbGUiOiJFdmVudEVtaXR0ZXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..d4cce30 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,42 @@ +const gulp = require('gulp'), + clean = require('gulp-clean'), + babel = require('gulp-babel'), + sourcemaps = require('gulp-sourcemaps'), + gutil = require('gulp-util'), + concat = require('gulp-concat'); + +gulp.task('build', () => { + gutil.log('Build for Node ...'); + gulp.src('src/**/*.js') + .pipe(babel({ + presets: ['es2015-node4'], + comments: false + }).on('error', err => gutil.log('Some shit appends for node dist ... ', err.message))) + .pipe(sourcemaps.init()) + .pipe(sourcemaps.write()) + .pipe(gulp.dest('dist_node')); + + gutil.log('Build for browser ...'); + gulp.src('src/**/*.js') + .pipe(babel({ + presets: ['es2015'], + comments: false + }).on('error', err => gutil.log('Some shit appends for browser dist ...', err.message))) + .pipe(sourcemaps.init()) + .pipe(concat('../bin/EventEmitter.browser.js')) + .pipe(sourcemaps.write()) + .pipe(gulp.dest('dist_browser')); +}); + +gulp.task('clean', () => { + gulp.src(['dist_node/**/*', 'dist_browser/**/*', 'temp'], {read: false}) + .pipe(clean()) +}); + +gulp.task('watch', ['cleanBuild'], () => { + gulp.watch(['bower.json', 'src/index.html'], ['bower']); + gulp.watch('src/**/*.js', ['build']); +}); + +gulp.task('default', ['watch']); +gulp.task('cleanBuild', ['clean', 'build']); diff --git a/package.json b/package.json new file mode 100644 index 0000000..ade53dd --- /dev/null +++ b/package.json @@ -0,0 +1,45 @@ +{ + "name": "eventemitter-promise", + "version": "0.0.1", + "description": "Event Emitter with lazy promise.", + "main": "bin/EventEmitter.node.js", + "scripts": { + "test": "mocha test/*.js" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/bios21/eventemitter-promise.git" + }, + "keywords": [ + "event", + "eventemitter", + "lazy", + "promise", + "a+", + "then", + "thenable" + ], + "devDependencies": { + "babel": "^6.5.2", + "babel-cli": "^6.10.1", + "babel-preset-es2015": "^6.9.0", + "babel-preset-es2015-node4": "^2.1.0", + "gulp": "^3.9.1", + "gulp-babel": "^6.1.2", + "gulp-clean": "^0.3.2", + "gulp-concat": "^2.6.0", + "gulp-sourcemaps": "^1.6.0", + "gulp-util": "^3.0.7", + "mocha": "^2.5.3", + "should": "^9.0.2" + }, + "author": "Lilian Saget-Lethias (http://github.com/bios21)", + "license": "ISC", + "bugs": { + "url": "https://github.com/bios21/eventemitter-promise/issues" + }, + "homepage": "https://github.com/bios21/eventemitter-promise#readme", + "dependencies": { + "superlazypromise": "0.0.1" + } +} diff --git a/src/EventEmitter.js b/src/EventEmitter.js new file mode 100644 index 0000000..3719e6a --- /dev/null +++ b/src/EventEmitter.js @@ -0,0 +1,188 @@ +'use strict'; + +var _module = null, + _exports = null; +if (module && module.exports) { + _exports = module.exports; + _module = { + SuperLazyPromise: require('superlazypromise').SuperLazyPromise + }; +} else { + _exports = window; + _module = _exports; +} + +((module, exports) => { + const SuperLazyPromise = module.SuperLazyPromise; + + const EMPTY_FN = function() {}, + NS_SEPARATOR = '.'; + + /** + * A manager for listening and emitting event on a object. + * + * + * Each listener are stored to be fired later on a `SuperLazyPromise` + * + * | emit\on | event | event.* | event.context | event.context! | + * |:--------------:|:-----:|:-------:|:-------------:|:--------------:| + * | event | ✓ | ✓ | ✓ | ✓ | + * | event.context | ✓ | | ✓ | ✓ | + * | event.context! | | | ✓ | ✓ | + * + * **!** : Firing an event on strict context (`event.context!`) is not yet implemented. + * + * @abstract + */ + class EventEmitter { + + /** + * Build the internal super lazy promise pool. + */ + constructor() { + + /** + * @type {Map} + * @private + */ + this._promises = new Map(); + } + + /** + * Listen the given event. + * Contrary to classic event manager like `addEventListener` for DOM, `EventEmitter` provide a `Promise`-like + * to manipulate instead of a callback. + * + * This `Promise` will be **SuperLazy** which means that it will be active only when we fire it. + * + * See `SuperLazyPromise` for more explanation. + * + * @param {String} event Type of event with context or not + * @return {LazyPromise} The promise to manipulate + * + * @see SuperLazyPromise + * @listening event + */ + on(event) { + let SLP = this._promises.get(event), + hasContext = event.includes(NS_SEPARATOR), + splitEvent = event.split(NS_SEPARATOR), + promiseMainEvent = this._promises.get(splitEvent[0]); + + if (hasContext) { + if (SLP) { + if (!promiseMainEvent) { + promiseMainEvent = new SuperLazyPromise(SLP.fn); + promiseMainEvent.updatePromise(SLP.promise); + this._promises.set(splitEvent[0], promiseMainEvent); + } + } else { + if (promiseMainEvent) { + SLP = new SuperLazyPromise(promiseMainEvent.fn); + SLP.updatePromise(promiseMainEvent.promise); + this._promises.set(event, SLP); + } else { + this._promises.set(splitEvent[0], new SuperLazyPromise(EMPTY_FN)); + this._promises.set(event, new SuperLazyPromise(EMPTY_FN)); + } + } + } else { + if (!SLP) { + this._promises.set(event, new SuperLazyPromise(EMPTY_FN)); + } + } + return this._promises.get(event); + } + + /** + * Stop listening on the given event. + * The promise stored by `on` or `emit` will become not usable. + * + * @param {String} event Type of event with context or not + * @listened event + */ + off(event) { + if (!event.includes(NS_SEPARATOR)) { + this._destroyPromise(event); + } else { + for (let keyVal of this._promises) { + if (keyVal[0].split(NS_SEPARATOR)[0] === event) { + this._destroyPromise(keyVal[0]); + } + } + } + } + + /** + * Kill & destroy a lazy promise to prevent future use. + * + * @param {String} event Type of event with context or not + * @private + */ + _destroyPromise(event) { + this._promises[event].kill(); + delete this._promises[event]; + } + + /** + * Emit a possibly listened event and call the function associated with some param. + * See the array in class description for event specific firing. + * + * @param {String} event Type of event with context or not + * @param {...*} data What is fired to the first listener + * + * @emit event + */ + emit(event, ...data) { + const executor = (ok, ko) => ok(...data); + + let SLP = this._promises.get(event), + hasContext = event.includes(NS_SEPARATOR), + splitEvent = event.split(NS_SEPARATOR), + promiseMainEvent = this._promises.get(splitEvent[0]); + + if (hasContext) { + if (SLP) { + SLP.awake(executor); + if (promiseMainEvent) { + promiseMainEvent.awake(executor); + } else { + promiseMainEvent = new SuperLazyPromise(EMPTY_FN); + promiseMainEvent.updatePromise(SLP.promise); + this._promises.set(splitEvent[0], promiseMainEvent); + } + } else { + if (promiseMainEvent) { + promiseMainEvent.awake(executor); + SLP = new SuperLazyPromise(EMPTY_FN); + SLP.updatePromise(promiseMainEvent.promise); + } else { + promiseMainEvent = new SuperLazyPromise(executor); + promiseMainEvent.awake(); + SLP = new SuperLazyPromise(EMPTY_FN); + SLP.updatePromise(promiseMainEvent.promise); + } + } + } else { + if (SLP) { + SLP.awake(executor); + } else { + SLP = new SuperLazyPromise(executor); + SLP.awake(); + this._promises.set(event, SLP); + } + + for (let keyVal of this._promises) { + if (keyVal[0].includes(NS_SEPARATOR) && keyVal[0].split(NS_SEPARATOR)[0] === event) { + let subEvent = keyVal[0], + subPromise = this._promises.get(subEvent); + subPromise.updatePromise(SLP.promise); + subPromise.awake(); + } + } + } + } + } + + exports.EventEmitter = EventEmitter; +})(_module, _exports); diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..8e49954 --- /dev/null +++ b/test/test.js @@ -0,0 +1,130 @@ +'use strict'; + +const EventEmitter = require('../dist_node/EventEmitter').EventEmitter, + mocha = require('mocha'), + should = require('should'); + +console.log(EventEmitter); + +describe('EventEmitter', () => { + describe('on/emit event => event', () => { + it('should emit and listen on event', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event').then(anything => { + anything.should.be.eql('test'); + done(); + }); + + test.emit('event', 'test'); + }); + + it('should emit on event and listen on event.test', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event.test').then(anything => { + anything.should.be.eql('test'); + done(); + }); + + test.emit('event', 'test'); + }); + + it('should emit on event.test and listen on event', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event').then(anything => { + anything.should.be.eql('test'); + done(); + }); + + test.emit('event.test', 'test'); + }); + + + it('should emit on "tneve" and listen on event without receiving', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event').then(anything => { + anything.should.not.be.eql('test'); + done(new Error('Should not be here.')); + }); + + test.emit('tneve', 'test'); + done(); + }); + }); + + describe('on/emit event.* => event.*', () => { + it('should emit and listen on event', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event.test').then(anything => { + anything.should.be.eql('test'); + done(); + }); + + test.emit('event.test', 'test'); + }); + + it('should emit on event and listen on event.test', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event.test').then(anything => { + anything.should.be.eql('test'); + done(); + }); + + test.emit('event', 'test'); + }); + + it('should emit on event.test and listen on event', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event').then(anything => { + anything.should.be.eql('test'); + done(); + }); + + test.emit('event.test', 'test'); + }); + + + it('should emit on "tneve" and listen on event without receiving', done => { + class Test extends EventEmitter { + + } + + let test = new Test(); + test.on('event').then(anything => { + anything.should.not.be.eql('test'); + done(new Error('Should not be here.')); + }); + + test.emit('tneve', 'test'); + done(); + }); + }); + +});