git-off

git off handles large files in git repos
git clone https://noulin.net/git/git-off.git
Log | Files | Refs | README

sequential_executor.js (7145B)


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