Merge pull request #60 from brodybits/events-singleton
Cordova events singleton object
diff --git a/src/events.js b/src/events.js
index 7038643..d16485c 100644
--- a/src/events.js
+++ b/src/events.js
@@ -17,56 +17,65 @@
under the License.
*/
-var EventEmitter = require('events').EventEmitter;
+const EventEmitter = require('events').EventEmitter;
-var INSTANCE = new EventEmitter();
-INSTANCE.setMaxListeners(20);
-var EVENTS_RECEIVER;
+const MAX_LISTENERS = 20;
-module.exports = INSTANCE;
+const INSTANCE_KEY = Symbol.for('org.apache.cordova.common.CordovaEvents');
-/**
- * Sets up current instance to forward emitted events to another EventEmitter
- * instance.
- *
- * @param {EventEmitter} [eventEmitter] The emitter instance to forward
- * events to. Falsy value, when passed, disables forwarding.
- */
-module.exports.forwardEventsTo = function (eventEmitter) {
+let EVENTS_RECEIVER = null;
- // If no argument is specified disable events forwarding
- if (!eventEmitter) {
- EVENTS_RECEIVER = undefined;
- return;
+class CordovaEventEmitter extends EventEmitter {
+ /**
+ * Sets up current instance to forward emitted events to another EventEmitter
+ * instance.
+ *
+ * @param {EventEmitter} [eventEmitter] The emitter instance to forward
+ * events to. Falsy value, when passed, disables forwarding.
+ */
+ forwardEventsTo (eventEmitter) {
+ // If no argument is specified disable events forwarding
+ if (!eventEmitter) {
+ EVENTS_RECEIVER = undefined;
+ return;
+ }
+
+ if (!(eventEmitter instanceof EventEmitter)) {
+ throw new Error('Cordova events can be redirected to another EventEmitter instance only');
+ }
+
+ // CB-10940 Skipping forwarding to self to avoid infinite recursion.
+ // This is the case when the modules are npm-linked.
+ if (this !== eventEmitter) {
+ EVENTS_RECEIVER = eventEmitter;
+ } else {
+ // Reset forwarding if we are subscribing to self
+ EVENTS_RECEIVER = undefined;
+ }
}
- if (!(eventEmitter instanceof EventEmitter)) { throw new Error('Cordova events can be redirected to another EventEmitter instance only'); }
+ /**
+ * Sets up current instance to forward emitted events to another EventEmitter
+ * instance.
+ *
+ * @param {EventEmitter} [eventEmitter] The emitter instance to forward
+ * events to. Falsy value, when passed, disables forwarding.
+ */
+ emit (eventName, ...args) {
+ if (EVENTS_RECEIVER) {
+ EVENTS_RECEIVER.emit(eventName, ...args);
+ }
- // CB-10940 Skipping forwarding to self to avoid infinite recursion.
- // This is the case when the modules are npm-linked.
- if (this !== eventEmitter) {
- EVENTS_RECEIVER = eventEmitter;
- } else {
- // Reset forwarding if we are subscribing to self
- EVENTS_RECEIVER = undefined;
+ return super.emit(eventName, ...args);
}
-};
+}
-var emit = INSTANCE.emit;
+// This singleton instance pattern is based on the ideas from
+// https://derickbailey.com/2016/03/09/creating-a-true-singleton-in-node-js-with-es6-symbols/
+if (Object.getOwnPropertySymbols(global).indexOf(INSTANCE_KEY) === -1) {
+ const events = new CordovaEventEmitter();
+ events.setMaxListeners(MAX_LISTENERS);
+ global[INSTANCE_KEY] = events;
+}
-/**
- * This method replaces original 'emit' method to allow events forwarding.
- *
- * @return {eventEmitter} Current instance to allow calls chaining, as
- * original 'emit' does
- */
-module.exports.emit = function () {
-
- var args = Array.prototype.slice.call(arguments);
-
- if (EVENTS_RECEIVER) {
- EVENTS_RECEIVER.emit.apply(EVENTS_RECEIVER, args);
- }
-
- return emit.apply(this, args);
-};
+module.exports = global[INSTANCE_KEY];