123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- var AWS = require('./core');
- /**
- * @api private
- * @!method on(eventName, callback)
- * Registers an event listener callback for the event given by `eventName`.
- * Parameters passed to the callback function depend on the individual event
- * being triggered. See the event documentation for those parameters.
- *
- * @param eventName [String] the event name to register the listener for
- * @param callback [Function] the listener callback function
- * @param toHead [Boolean] attach the listener callback to the head of callback array if set to true.
- * Default to be false.
- * @return [AWS.SequentialExecutor] the same object for chaining
- */
- AWS.SequentialExecutor = AWS.util.inherit({
- constructor: function SequentialExecutor() {
- this._events = {};
- },
- /**
- * @api private
- */
- listeners: function listeners(eventName) {
- return this._events[eventName] ? this._events[eventName].slice(0) : [];
- },
- on: function on(eventName, listener, toHead) {
- if (this._events[eventName]) {
- toHead ?
- this._events[eventName].unshift(listener) :
- this._events[eventName].push(listener);
- } else {
- this._events[eventName] = [listener];
- }
- return this;
- },
- onAsync: function onAsync(eventName, listener, toHead) {
- listener._isAsync = true;
- return this.on(eventName, listener, toHead);
- },
- removeListener: function removeListener(eventName, listener) {
- var listeners = this._events[eventName];
- if (listeners) {
- var length = listeners.length;
- var position = -1;
- for (var i = 0; i < length; ++i) {
- if (listeners[i] === listener) {
- position = i;
- }
- }
- if (position > -1) {
- listeners.splice(position, 1);
- }
- }
- return this;
- },
- removeAllListeners: function removeAllListeners(eventName) {
- if (eventName) {
- delete this._events[eventName];
- } else {
- this._events = {};
- }
- return this;
- },
- /**
- * @api private
- */
- emit: function emit(eventName, eventArgs, doneCallback) {
- if (!doneCallback) doneCallback = function() { };
- var listeners = this.listeners(eventName);
- var count = listeners.length;
- this.callListeners(listeners, eventArgs, doneCallback);
- return count > 0;
- },
- /**
- * @api private
- */
- callListeners: function callListeners(listeners, args, doneCallback, prevError) {
- var self = this;
- var error = prevError || null;
- function callNextListener(err) {
- if (err) {
- error = AWS.util.error(error || new Error(), err);
- if (self._haltHandlersOnError) {
- return doneCallback.call(self, error);
- }
- }
- self.callListeners(listeners, args, doneCallback, error);
- }
- while (listeners.length > 0) {
- var listener = listeners.shift();
- if (listener._isAsync) { // asynchronous listener
- listener.apply(self, args.concat([callNextListener]));
- return; // stop here, callNextListener will continue
- } else { // synchronous listener
- try {
- listener.apply(self, args);
- } catch (err) {
- error = AWS.util.error(error || new Error(), err);
- }
- if (error && self._haltHandlersOnError) {
- doneCallback.call(self, error);
- return;
- }
- }
- }
- doneCallback.call(self, error);
- },
- /**
- * Adds or copies a set of listeners from another list of
- * listeners or SequentialExecutor object.
- *
- * @param listeners [map<String,Array<Function>>, AWS.SequentialExecutor]
- * a list of events and callbacks, or an event emitter object
- * containing listeners to add to this emitter object.
- * @return [AWS.SequentialExecutor] the emitter object, for chaining.
- * @example Adding listeners from a map of listeners
- * emitter.addListeners({
- * event1: [function() { ... }, function() { ... }],
- * event2: [function() { ... }]
- * });
- * emitter.emit('event1'); // emitter has event1
- * emitter.emit('event2'); // emitter has event2
- * @example Adding listeners from another emitter object
- * var emitter1 = new AWS.SequentialExecutor();
- * emitter1.on('event1', function() { ... });
- * emitter1.on('event2', function() { ... });
- * var emitter2 = new AWS.SequentialExecutor();
- * emitter2.addListeners(emitter1);
- * emitter2.emit('event1'); // emitter2 has event1
- * emitter2.emit('event2'); // emitter2 has event2
- */
- addListeners: function addListeners(listeners) {
- var self = this;
- // extract listeners if parameter is an SequentialExecutor object
- if (listeners._events) listeners = listeners._events;
- AWS.util.each(listeners, function(event, callbacks) {
- if (typeof callbacks === 'function') callbacks = [callbacks];
- AWS.util.arrayEach(callbacks, function(callback) {
- self.on(event, callback);
- });
- });
- return self;
- },
- /**
- * Registers an event with {on} and saves the callback handle function
- * as a property on the emitter object using a given `name`.
- *
- * @param name [String] the property name to set on this object containing
- * the callback function handle so that the listener can be removed in
- * the future.
- * @param (see on)
- * @return (see on)
- * @example Adding a named listener DATA_CALLBACK
- * var listener = function() { doSomething(); };
- * emitter.addNamedListener('DATA_CALLBACK', 'data', listener);
- *
- * // the following prints: true
- * console.log(emitter.DATA_CALLBACK == listener);
- */
- addNamedListener: function addNamedListener(name, eventName, callback, toHead) {
- this[name] = callback;
- this.addListener(eventName, callback, toHead);
- return this;
- },
- /**
- * @api private
- */
- addNamedAsyncListener: function addNamedAsyncListener(name, eventName, callback, toHead) {
- callback._isAsync = true;
- return this.addNamedListener(name, eventName, callback, toHead);
- },
- /**
- * Helper method to add a set of named listeners using
- * {addNamedListener}. The callback contains a parameter
- * with a handle to the `addNamedListener` method.
- *
- * @callback callback function(add)
- * The callback function is called immediately in order to provide
- * the `add` function to the block. This simplifies the addition of
- * a large group of named listeners.
- * @param add [Function] the {addNamedListener} function to call
- * when registering listeners.
- * @example Adding a set of named listeners
- * emitter.addNamedListeners(function(add) {
- * add('DATA_CALLBACK', 'data', function() { ... });
- * add('OTHER', 'otherEvent', function() { ... });
- * add('LAST', 'lastEvent', function() { ... });
- * });
- *
- * // these properties are now set:
- * emitter.DATA_CALLBACK;
- * emitter.OTHER;
- * emitter.LAST;
- */
- addNamedListeners: function addNamedListeners(callback) {
- var self = this;
- callback(
- function() {
- self.addNamedListener.apply(self, arguments);
- },
- function() {
- self.addNamedAsyncListener.apply(self, arguments);
- }
- );
- return this;
- }
- });
- /**
- * {on} is the prefered method.
- * @api private
- */
- AWS.SequentialExecutor.prototype.addListener = AWS.SequentialExecutor.prototype.on;
- /**
- * @api private
- */
- module.exports = AWS.SequentialExecutor;
|