/ cloudformation-templates / node_modules / aws-cdk / node_modules / aws-sdk / lib / sequential_executor.js
sequential_executor.js
1 var AWS = require('./core'); 2 3 /** 4 * @api private 5 * @!method on(eventName, callback) 6 * Registers an event listener callback for the event given by `eventName`. 7 * Parameters passed to the callback function depend on the individual event 8 * being triggered. See the event documentation for those parameters. 9 * 10 * @param eventName [String] the event name to register the listener for 11 * @param callback [Function] the listener callback function 12 * @param toHead [Boolean] attach the listener callback to the head of callback array if set to true. 13 * Default to be false. 14 * @return [AWS.SequentialExecutor] the same object for chaining 15 */ 16 AWS.SequentialExecutor = AWS.util.inherit({ 17 18 constructor: function SequentialExecutor() { 19 this._events = {}; 20 }, 21 22 /** 23 * @api private 24 */ 25 listeners: function listeners(eventName) { 26 return this._events[eventName] ? this._events[eventName].slice(0) : []; 27 }, 28 29 on: function on(eventName, listener, toHead) { 30 if (this._events[eventName]) { 31 toHead ? 32 this._events[eventName].unshift(listener) : 33 this._events[eventName].push(listener); 34 } else { 35 this._events[eventName] = [listener]; 36 } 37 return this; 38 }, 39 40 onAsync: function onAsync(eventName, listener, toHead) { 41 listener._isAsync = true; 42 return this.on(eventName, listener, toHead); 43 }, 44 45 removeListener: function removeListener(eventName, listener) { 46 var listeners = this._events[eventName]; 47 if (listeners) { 48 var length = listeners.length; 49 var position = -1; 50 for (var i = 0; i < length; ++i) { 51 if (listeners[i] === listener) { 52 position = i; 53 } 54 } 55 if (position > -1) { 56 listeners.splice(position, 1); 57 } 58 } 59 return this; 60 }, 61 62 removeAllListeners: function removeAllListeners(eventName) { 63 if (eventName) { 64 delete this._events[eventName]; 65 } else { 66 this._events = {}; 67 } 68 return this; 69 }, 70 71 /** 72 * @api private 73 */ 74 emit: function emit(eventName, eventArgs, doneCallback) { 75 if (!doneCallback) doneCallback = function() { }; 76 var listeners = this.listeners(eventName); 77 var count = listeners.length; 78 this.callListeners(listeners, eventArgs, doneCallback); 79 return count > 0; 80 }, 81 82 /** 83 * @api private 84 */ 85 callListeners: function callListeners(listeners, args, doneCallback, prevError) { 86 var self = this; 87 var error = prevError || null; 88 89 function callNextListener(err) { 90 if (err) { 91 error = AWS.util.error(error || new Error(), err); 92 if (self._haltHandlersOnError) { 93 return doneCallback.call(self, error); 94 } 95 } 96 self.callListeners(listeners, args, doneCallback, error); 97 } 98 99 while (listeners.length > 0) { 100 var listener = listeners.shift(); 101 if (listener._isAsync) { // asynchronous listener 102 listener.apply(self, args.concat([callNextListener])); 103 return; // stop here, callNextListener will continue 104 } else { // synchronous listener 105 try { 106 listener.apply(self, args); 107 } catch (err) { 108 error = AWS.util.error(error || new Error(), err); 109 } 110 if (error && self._haltHandlersOnError) { 111 doneCallback.call(self, error); 112 return; 113 } 114 } 115 } 116 doneCallback.call(self, error); 117 }, 118 119 /** 120 * Adds or copies a set of listeners from another list of 121 * listeners or SequentialExecutor object. 122 * 123 * @param listeners [map<String,Array<Function>>, AWS.SequentialExecutor] 124 * a list of events and callbacks, or an event emitter object 125 * containing listeners to add to this emitter object. 126 * @return [AWS.SequentialExecutor] the emitter object, for chaining. 127 * @example Adding listeners from a map of listeners 128 * emitter.addListeners({ 129 * event1: [function() { ... }, function() { ... }], 130 * event2: [function() { ... }] 131 * }); 132 * emitter.emit('event1'); // emitter has event1 133 * emitter.emit('event2'); // emitter has event2 134 * @example Adding listeners from another emitter object 135 * var emitter1 = new AWS.SequentialExecutor(); 136 * emitter1.on('event1', function() { ... }); 137 * emitter1.on('event2', function() { ... }); 138 * var emitter2 = new AWS.SequentialExecutor(); 139 * emitter2.addListeners(emitter1); 140 * emitter2.emit('event1'); // emitter2 has event1 141 * emitter2.emit('event2'); // emitter2 has event2 142 */ 143 addListeners: function addListeners(listeners) { 144 var self = this; 145 146 // extract listeners if parameter is an SequentialExecutor object 147 if (listeners._events) listeners = listeners._events; 148 149 AWS.util.each(listeners, function(event, callbacks) { 150 if (typeof callbacks === 'function') callbacks = [callbacks]; 151 AWS.util.arrayEach(callbacks, function(callback) { 152 self.on(event, callback); 153 }); 154 }); 155 156 return self; 157 }, 158 159 /** 160 * Registers an event with {on} and saves the callback handle function 161 * as a property on the emitter object using a given `name`. 162 * 163 * @param name [String] the property name to set on this object containing 164 * the callback function handle so that the listener can be removed in 165 * the future. 166 * @param (see on) 167 * @return (see on) 168 * @example Adding a named listener DATA_CALLBACK 169 * var listener = function() { doSomething(); }; 170 * emitter.addNamedListener('DATA_CALLBACK', 'data', listener); 171 * 172 * // the following prints: true 173 * console.log(emitter.DATA_CALLBACK == listener); 174 */ 175 addNamedListener: function addNamedListener(name, eventName, callback, toHead) { 176 this[name] = callback; 177 this.addListener(eventName, callback, toHead); 178 return this; 179 }, 180 181 /** 182 * @api private 183 */ 184 addNamedAsyncListener: function addNamedAsyncListener(name, eventName, callback, toHead) { 185 callback._isAsync = true; 186 return this.addNamedListener(name, eventName, callback, toHead); 187 }, 188 189 /** 190 * Helper method to add a set of named listeners using 191 * {addNamedListener}. The callback contains a parameter 192 * with a handle to the `addNamedListener` method. 193 * 194 * @callback callback function(add) 195 * The callback function is called immediately in order to provide 196 * the `add` function to the block. This simplifies the addition of 197 * a large group of named listeners. 198 * @param add [Function] the {addNamedListener} function to call 199 * when registering listeners. 200 * @example Adding a set of named listeners 201 * emitter.addNamedListeners(function(add) { 202 * add('DATA_CALLBACK', 'data', function() { ... }); 203 * add('OTHER', 'otherEvent', function() { ... }); 204 * add('LAST', 'lastEvent', function() { ... }); 205 * }); 206 * 207 * // these properties are now set: 208 * emitter.DATA_CALLBACK; 209 * emitter.OTHER; 210 * emitter.LAST; 211 */ 212 addNamedListeners: function addNamedListeners(callback) { 213 var self = this; 214 callback( 215 function() { 216 self.addNamedListener.apply(self, arguments); 217 }, 218 function() { 219 self.addNamedAsyncListener.apply(self, arguments); 220 } 221 ); 222 return this; 223 } 224 }); 225 226 /** 227 * {on} is the prefered method. 228 * @api private 229 */ 230 AWS.SequentialExecutor.prototype.addListener = AWS.SequentialExecutor.prototype.on; 231 232 /** 233 * @api private 234 */ 235 module.exports = AWS.SequentialExecutor;