emitter.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. function getListeners(emitter, type) {
  2. if (!emitter._events) emitter._events = Object.create(null);
  3. return emitter._events[type] || (emitter._events[type] = []);
  4. }
  5. function assertIsFunction(fn, name) {
  6. if (typeof fn !== "function") {
  7. throw new Error(name + ' must be a function');
  8. }
  9. }
  10. export default class Emitter {
  11. on(channel, listener) {
  12. if (Array.isArray(channel)) {
  13. channel.forEach(c => this.on(c, listener));
  14. } else {
  15. assertIsFunction(listener, 'listener');
  16. getListeners(this, channel).push(listener);
  17. }
  18. return this;
  19. }
  20. once(channel, listener) {
  21. assertIsFunction(listener, 'listener');
  22. function fn(...args) {
  23. if (fn.called) return;
  24. this.off(channel, fn);
  25. fn.called = true;
  26. listener(...args);
  27. }
  28. fn.listener = listener;
  29. fn.called = false;
  30. return this.on(channel, fn);
  31. }
  32. off(channel, listener) {
  33. if (Array.isArray(channel)) {
  34. channel.forEach(c => this.off(c, listener));
  35. return;
  36. }
  37. let listeners;
  38. if (!this._events || !(listeners = getListeners(this, channel)).length) {
  39. return;
  40. }
  41. if (!listener) {
  42. listeners.length = 0;
  43. return;
  44. }
  45. assertIsFunction(listener, 'listener');
  46. for (let i = listeners.length - 1; i >= 0; i--) {
  47. const fn = listeners[i];
  48. if (fn === listener || fn.listener === listener) {
  49. listeners.splice(i, 1);
  50. }
  51. }
  52. }
  53. emit(channel, ...args) {
  54. getListeners(this, channel).forEach(listener => {
  55. listener.apply(this, args);
  56. });
  57. }
  58. }