events.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*!
  2. * awsome-events v1.0.15
  3. * (c) ghostratel
  4. * Released under the MIT License.
  5. */
  6. (function (global, factory) {
  7. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  8. typeof define === 'function' && define.amd ? define(factory) :
  9. (global = global || self, global.Events = factory());
  10. }(this, function () { 'use strict';
  11. function _typeof(obj) {
  12. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  13. _typeof = function (obj) {
  14. return typeof obj;
  15. };
  16. } else {
  17. _typeof = function (obj) {
  18. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  19. };
  20. }
  21. return _typeof(obj);
  22. }
  23. function checkListener(listener) {
  24. if (typeof listener !== 'function') {
  25. throw new TypeError('The "listener" argument must be of type Function. Received type ' + _typeof(listener));
  26. }
  27. }
  28. function emitAllListeners(listeners) {
  29. var i = 0;
  30. for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  31. args[_key - 1] = arguments[_key];
  32. }
  33. while (i < listeners.length) {
  34. var _listeners$i;
  35. (_listeners$i = listeners[i]).call.apply(_listeners$i, [this].concat(args));
  36. listeners[i].once && (listeners.splice(i, 1), i--); // when using splice will make the array length -1, so let the index -1 too
  37. i++;
  38. }
  39. }
  40. function checkListenersLimit(eventName, listeners) {
  41. if (listeners.length > this._maxListeners && !listeners.warned) {
  42. console.warn("Possible EventEmitter memory leak detected. ".concat(listeners.length, " '").concat(eventName, "' ") + 'listeners added. Use emitter.setMaxListeners() to increase limit.');
  43. listeners.warned = true;
  44. }
  45. }
  46. function findFromTail(list, cb) {
  47. var i = list.length;
  48. var ret = -1;
  49. while (i) {
  50. --i;
  51. var _ret = cb(list[i], i);
  52. if (_ret) {
  53. ret = i;
  54. break;
  55. }
  56. }
  57. return ret;
  58. }
  59. var Events = function Events() {
  60. this._events = {};
  61. var _maxListeners;
  62. Object.defineProperty(this, '_maxListeners', {
  63. get: function get() {
  64. // when Events instance has '_maxListeners', use instance's '_maxListeners'
  65. // when Events instance don't has '_maxListeners', use Events.defaultMaxListeners
  66. return _maxListeners ? _maxListeners : this.defaultMaxListeners;
  67. },
  68. set: function set(n) {
  69. if (n < 0 || isNaN(n) || typeof n !== 'number') {
  70. throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
  71. }
  72. _maxListeners = n;
  73. }
  74. });
  75. };
  76. Events.prototype.defaultMaxListeners = 10;
  77. Events.prototype.on = Events.prototype.addListener = function (eventName, listener) {
  78. checkListener(listener);
  79. if (!this._events[eventName]) {
  80. this._events[eventName] = [];
  81. }
  82. this._events['newListener'] && emitAllListeners.call(this, this._events['newListener']);
  83. this._events[eventName].push(listener);
  84. checkListenersLimit.call(this, eventName, this._events[eventName]);
  85. };
  86. Events.prototype.off = Events.prototype.removeListener = function (eventName, listener) {
  87. checkListener(listener);
  88. var listeners = this._events[eventName];
  89. if (!listeners) {
  90. return this;
  91. }
  92. var context = this;
  93. var listenerIndex = findFromTail(listeners, function (_lisener) {
  94. var _funcName = _lisener.name.match(/bound\s(\w*)/) ? _lisener.name.match(/bound\s([_\w]*)/)[1] : _lisener.name;
  95. var _lisenerName = listener.name.match(/bound\s(\w*)/) ? listener.name.match(/bound\s(\w*)/)[1] : listener.name;
  96. if (_lisener.once) {
  97. return _funcName === _lisenerName && _lisener.toString() === listener.bind(context).toString();
  98. } else {
  99. return _funcName === _lisenerName && _lisener.toString() === listener.toString();
  100. }
  101. });
  102. if (listenerIndex !== -1) {
  103. listeners.splice(listenerIndex, 1); // if no listeners, delete the event
  104. if (listeners.length === 0) {
  105. delete this._events[eventName];
  106. }
  107. this._events['removeListener'] && emitAllListeners.call(this, this._events['removeListener']);
  108. }
  109. return this;
  110. };
  111. Events.prototype.emit = function (eventName) {
  112. if (this._events.hasOwnProperty(eventName)) {
  113. var listeners = this._events[eventName];
  114. for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  115. args[_key - 1] = arguments[_key];
  116. }
  117. emitAllListeners.call.apply(emitAllListeners, [this, listeners].concat(args));
  118. listeners.length === 0 && delete this._events[eventName];
  119. return true;
  120. } else {
  121. return false;
  122. }
  123. };
  124. Events.prototype.once = function (eventName, listener) {
  125. checkListener(listener);
  126. var bound = listener.bind(this);
  127. this.addListener(eventName, bound);
  128. bound.once = true;
  129. return this;
  130. };
  131. Events.prototype.removeAllListeners = function (eventName) {
  132. var listeners = this._events[eventName];
  133. var l = listeners.length;
  134. while (l) {
  135. this._events['removeListener'] && emitAllListeners.call(this, this._events['removeListener']);
  136. l--;
  137. }
  138. listeners && delete this._events[eventName];
  139. return this;
  140. };
  141. Events.prototype.prependListener = function (eventName, listener) {
  142. checkListener(listener);
  143. if (!this._events[eventName]) {
  144. this._events[eventName] = [];
  145. }
  146. this._events['newListener'] && emitAllListeners.call(this, this._events['newListener']);
  147. this._events[eventName].unshift(listener);
  148. checkListenersLimit.call(this, eventName, this._events[eventName]);
  149. };
  150. Events.prototype.prependOnceListener = function (eventName, listener) {
  151. checkListener(listener);
  152. var bound = listener.bind(this);
  153. this.prependListener(eventName, bound);
  154. bound.once = true;
  155. return this;
  156. };
  157. Events.prototype.listenerCount = function (eventName) {
  158. return this._events[eventName] ? this._events[eventName].length : 0;
  159. };
  160. Events.prototype.eventNames = function () {
  161. return Object.keys(this._events);
  162. };
  163. Events.prototype.listeners = function (eventName) {
  164. return this._events.hasOwnProperty(eventName) ? this._events[eventName].slice() : [];
  165. };
  166. Events.prototype.setMaxListeners = function (n) {
  167. if (n < 0 || isNaN(n) || typeof n !== 'number') {
  168. throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
  169. }
  170. this._maxListeners = n;
  171. };
  172. Events.prototype.getMaxListeners = function () {
  173. return this._maxListeners;
  174. };
  175. Events.prototype.rawListeners = function (eventName) {
  176. var instance = this;
  177. var listeners = this._events[eventName] ? this._events[eventName].slice() : [];
  178. listeners.length && (listeners = listeners.map(function (listener, _i) {
  179. var f = function f() {
  180. if (listener.once) {
  181. instance.removeListener(eventName, listener);
  182. listeners.splice(_i, 1);
  183. if (listeners.length === 0) {
  184. delete instance._events[eventName];
  185. }
  186. }
  187. listener();
  188. };
  189. if (listener.once) {
  190. f.listener = function () {
  191. listener();
  192. };
  193. f.listener.once = listener.once;
  194. }
  195. return f;
  196. }));
  197. return listeners;
  198. };
  199. return Events;
  200. }));