custom-event-emitter.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. var util = require("util")
  2. , EventEmitter = require("events").EventEmitter
  3. , Promise = require("bluebird")
  4. , proxyEventKeys = ['success', 'error', 'sql']
  5. , Utils = require('../utils')
  6. var bindToProcess = function(fct) {
  7. if (fct && process.domain) {
  8. return process.domain.bind(fct)
  9. }
  10. return fct
  11. };
  12. module.exports = (function() {
  13. var CustomEventEmitter = function(fct) {
  14. this.fct = bindToProcess(fct)
  15. }
  16. util.inherits(CustomEventEmitter, EventEmitter)
  17. CustomEventEmitter.prototype.run = function() {
  18. Utils.tick(function() {
  19. if (this.fct) {
  20. this.fct.call(this, this)
  21. }
  22. }.bind(this))
  23. return this
  24. }
  25. CustomEventEmitter.prototype.emit = function(type) {
  26. this._events = this._events || {};
  27. // Override default 'error' event logic
  28. if (type === 'error' && !this._events.error) {
  29. // No error listener
  30. var er = arguments[1];
  31. // If error argument is an object but no error,
  32. // boil it down to the value of the first key
  33. // (probably an Array in most cases)
  34. if (Utils._.isObject(er) && !(er instanceof Error)) {
  35. er = er[Object.keys(er)[0]]
  36. }
  37. // If error argument is an array, make sure we
  38. // pass only the first error to the original
  39. // .emit() function of EventEmitter
  40. if (er instanceof Array) {
  41. er = Utils._.flatten(er)[0]
  42. }
  43. // We don't want to throw strings. Make them Errors!
  44. if (typeof er === "string") {
  45. er = new Error(er)
  46. }
  47. arguments[1] = er
  48. }
  49. EventEmitter.prototype.emit.apply(this, arguments);
  50. };
  51. /**
  52. Shortcut methods (success, ok) for listening for success events.
  53. Params:
  54. - fct: A function that gets executed once the *success* event was triggered.
  55. Result:
  56. The function returns the instance of the query.
  57. */
  58. CustomEventEmitter.prototype.success =
  59. CustomEventEmitter.prototype.ok =
  60. function(fct) {
  61. this.on('success', bindToProcess(fct))
  62. return this
  63. }
  64. /**
  65. Shortcut methods (failure, fail, error) for listening for error events.
  66. Params:
  67. - fct: A function that gets executed once the *error* event was triggered.
  68. Result:
  69. The function returns the instance of the query.
  70. */
  71. CustomEventEmitter.prototype.failure =
  72. CustomEventEmitter.prototype.fail =
  73. CustomEventEmitter.prototype.error =
  74. function(fct) {
  75. this.on('error', bindToProcess(fct))
  76. return this;
  77. }
  78. CustomEventEmitter.prototype.done =
  79. CustomEventEmitter.prototype.complete =
  80. function(fct) {
  81. fct = bindToProcess(fct);
  82. this.on('error', function(err) { fct(err, null) })
  83. .on('success', function() {
  84. var args = Array.prototype.slice.call(arguments);
  85. args.unshift(null);
  86. fct.apply(fct, args);
  87. })
  88. return this
  89. }
  90. CustomEventEmitter.prototype.sql = function(fct) {
  91. this.on('sql', bindToProcess(fct))
  92. return this;
  93. }
  94. /**
  95. * Proxy every event of this custom event emitter to another one.
  96. *
  97. * @param {CustomEventEmitter} emitter The event emitter that should receive the events.
  98. * @return {void}
  99. */
  100. CustomEventEmitter.prototype.proxy = function(emitter, options) {
  101. options = Utils._.extend({
  102. events: proxyEventKeys,
  103. skipEvents: []
  104. }, options || {})
  105. options.events = Utils._.difference(options.events, options.skipEvents)
  106. options.events.forEach(function (eventKey) {
  107. this.on(eventKey, function (result) {
  108. emitter.emit(eventKey, result)
  109. })
  110. }.bind(this))
  111. return this
  112. }
  113. CustomEventEmitter.prototype.then = function(onFulfilled, onRejected) {
  114. var self = this
  115. onFulfilled = bindToProcess(onFulfilled)
  116. onRejected = bindToProcess(onRejected)
  117. return new Promise(function (resolve, reject) {
  118. self.on('error', reject)
  119. .on('success', resolve)
  120. }).then(onFulfilled, onRejected)
  121. }
  122. CustomEventEmitter.prototype.spread = function(onFulfilled, onRejected) {
  123. var self = this
  124. onFulfilled = bindToProcess(onFulfilled)
  125. onRejected = bindToProcess(onRejected)
  126. return new Promise(function (resolve, reject) {
  127. self.on('error', reject)
  128. .on('success', function () {
  129. resolve(Array.prototype.slice.apply(arguments)) // Transform args to an array
  130. })
  131. }).spread(onFulfilled, onRejected)
  132. }
  133. return CustomEventEmitter
  134. })()