query-chainer.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. var Utils = require(__dirname + "/utils")
  2. module.exports = (function() {
  3. var QueryChainer = function(emitters) {
  4. var self = this
  5. this.finishedEmits = 0
  6. this.emitters = []
  7. this.serials = []
  8. this.fails = []
  9. this.serialResults = []
  10. this.emitterResults = []
  11. this.finished = false
  12. this.wasRunning = false
  13. this.eventEmitter = null
  14. emitters = emitters || []
  15. emitters.forEach(function(emitter) {
  16. if (Array.isArray(emitter)) {
  17. self.add.apply(self, emitter)
  18. } else {
  19. self.add(emitter)
  20. }
  21. })
  22. }
  23. QueryChainer.prototype.add = function(emitterOrKlass, method, params, options) {
  24. if (!!method) {
  25. this.serials.push({ klass: emitterOrKlass, method: method, params: params, options: options })
  26. } else {
  27. observeEmitter.call(this, emitterOrKlass)
  28. this.emitters.push(emitterOrKlass)
  29. }
  30. return this
  31. }
  32. QueryChainer.prototype.run = function() {
  33. var self = this
  34. this.eventEmitter = new Utils.CustomEventEmitter(function() {
  35. self.wasRunning = true
  36. finish.call(self, 'emitterResults')
  37. })
  38. return this.eventEmitter.run()
  39. }
  40. QueryChainer.prototype.runSerially = function(options) {
  41. var self = this
  42. , serialCopy = Utils._.clone(this.serials)
  43. options = Utils._.extend({
  44. skipOnError: false
  45. }, options)
  46. var exec = function() {
  47. var serial = self.serials.pop()
  48. if (serial) {
  49. serial.options = serial.options || {}
  50. serial.options.before && serial.options.before(serial.klass)
  51. var onSuccess = function() {
  52. serial.options.after && serial.options.after(serial.klass)
  53. self.finishedEmits++
  54. exec()
  55. }
  56. var onError = function(err) {
  57. serial.options.after && serial.options.after(serial.klass)
  58. self.finishedEmits++
  59. self.fails.push(err)
  60. exec()
  61. }
  62. if (options.skipOnError && (self.fails.length > 0)) {
  63. onError('Skipped due to earlier error!')
  64. } else {
  65. if (typeof serial.options === "object" && Object.keys(serial.options).length > 0 && serial.method === "queryAndEmit") {
  66. serial.params.push(serial.options)
  67. }
  68. var emitter = serial.klass[serial.method].apply(serial.klass, serial.params)
  69. emitter.success(function(result) {
  70. self.serialResults[serialCopy.indexOf(serial)] = result
  71. if (serial.options.success) {
  72. serial.options.success(serial.klass, onSuccess)
  73. } else {
  74. onSuccess()
  75. }
  76. }).error(onError)
  77. }
  78. } else {
  79. self.wasRunning = true
  80. finish.call(self, 'serialResults')
  81. }
  82. }
  83. this.serials.reverse()
  84. this.eventEmitter = new Utils.CustomEventEmitter(exec)
  85. return this.eventEmitter.run()
  86. }
  87. // private
  88. var observeEmitter = function(emitter) {
  89. var self = this
  90. emitter
  91. .success(function(result) {
  92. self.emitterResults[self.emitters.indexOf(emitter)] = result
  93. self.finishedEmits++
  94. finish.call(self, 'emitterResults')
  95. })
  96. .error(function(err) {
  97. self.finishedEmits++
  98. self.fails.push(err)
  99. finish.call(self, 'emitterResults')
  100. })
  101. .on('sql', function(sql) {
  102. if (self.eventEmitter) {
  103. self.eventEmitter.emit('sql', sql)
  104. }
  105. })
  106. }
  107. var finish = function(resultsName) {
  108. this.finished = true
  109. if (this.emitters.length > 0) {
  110. this.finished = (this.finishedEmits === this.emitters.length)
  111. }
  112. else if (this.serials.length > 0) {
  113. this.finished = (this.finishedEmits === this.serials.length)
  114. }
  115. if (this.finished && this.wasRunning) {
  116. var status = (this.fails.length === 0 ? 'success' : 'error')
  117. , result = (this.fails.length === 0 ? this[resultsName] : this.fails)
  118. this.eventEmitter.emit.apply(this.eventEmitter, [status, result].concat(result))
  119. }
  120. }
  121. return QueryChainer
  122. })()