var Utils = require(__dirname + "/utils") module.exports = (function() { var QueryChainer = function(emitters) { var self = this this.finishedEmits = 0 this.emitters = [] this.serials = [] this.fails = [] this.serialResults = [] this.emitterResults = [] this.finished = false this.wasRunning = false this.eventEmitter = null emitters = emitters || [] emitters.forEach(function(emitter) { if (Array.isArray(emitter)) { self.add.apply(self, emitter) } else { self.add(emitter) } }) } QueryChainer.prototype.add = function(emitterOrKlass, method, params, options) { if (!!method) { this.serials.push({ klass: emitterOrKlass, method: method, params: params, options: options }) } else { observeEmitter.call(this, emitterOrKlass) this.emitters.push(emitterOrKlass) } return this } QueryChainer.prototype.run = function() { var self = this this.eventEmitter = new Utils.CustomEventEmitter(function() { self.wasRunning = true finish.call(self, 'emitterResults') }) return this.eventEmitter.run() } QueryChainer.prototype.runSerially = function(options) { var self = this , serialCopy = Utils._.clone(this.serials) options = Utils._.extend({ skipOnError: false }, options) var exec = function() { var serial = self.serials.pop() if (serial) { serial.options = serial.options || {} serial.options.before && serial.options.before(serial.klass) var onSuccess = function() { serial.options.after && serial.options.after(serial.klass) self.finishedEmits++ exec() } var onError = function(err) { serial.options.after && serial.options.after(serial.klass) self.finishedEmits++ self.fails.push(err) exec() } if (options.skipOnError && (self.fails.length > 0)) { onError('Skipped due to earlier error!') } else { if (typeof serial.options === "object" && Object.keys(serial.options).length > 0 && serial.method === "queryAndEmit") { serial.params.push(serial.options) } var emitter = serial.klass[serial.method].apply(serial.klass, serial.params) emitter.success(function(result) { self.serialResults[serialCopy.indexOf(serial)] = result if (serial.options.success) { serial.options.success(serial.klass, onSuccess) } else { onSuccess() } }).error(onError) } } else { self.wasRunning = true finish.call(self, 'serialResults') } } this.serials.reverse() this.eventEmitter = new Utils.CustomEventEmitter(exec) return this.eventEmitter.run() } // private var observeEmitter = function(emitter) { var self = this emitter .success(function(result) { self.emitterResults[self.emitters.indexOf(emitter)] = result self.finishedEmits++ finish.call(self, 'emitterResults') }) .error(function(err) { self.finishedEmits++ self.fails.push(err) finish.call(self, 'emitterResults') }) .on('sql', function(sql) { if (self.eventEmitter) { self.eventEmitter.emit('sql', sql) } }) } var finish = function(resultsName) { this.finished = true if (this.emitters.length > 0) { this.finished = (this.finishedEmits === this.emitters.length) } else if (this.serials.length > 0) { this.finished = (this.finishedEmits === this.serials.length) } if (this.finished && this.wasRunning) { var status = (this.fails.length === 0 ? 'success' : 'error') , result = (this.fails.length === 0 ? this[resultsName] : this.fails) this.eventEmitter.emit.apply(this.eventEmitter, [status, result].concat(result)) } } return QueryChainer })()