EventEmitter.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // Simple event emitter implementation, but has a slightly unusual API for
  2. // removing specific listeners. If a specific listener needs to be removed
  3. // (instead of all listeners), then it needs to use a "namespace":
  4. // Create a listener on the foo event with bar namespace: .on 'foo.bar'
  5. // Trigger all events for the foo event (including namespaces): .trigger 'foo'
  6. // Remove all listeners for the foo event (including namespaces): .off 'foo'
  7. // Remove a listener for the foo event with the bar namespace: .off 'foo.bar'
  8. export default class EventEmitter {
  9. events: Record<
  10. string,
  11. {
  12. callback: (...args: any[]) => void
  13. namespace: string
  14. }[]
  15. >
  16. constructor() {
  17. this.events = {}
  18. }
  19. on(event: string, callback: (...args: any[]) => void) {
  20. if (!this.events) {
  21. this.events = {}
  22. }
  23. let namespace
  24. ;[event, namespace] = Array.from(event.split('.'))
  25. if (!this.events[event]) {
  26. this.events[event] = []
  27. }
  28. this.events[event].push({
  29. callback,
  30. namespace,
  31. })
  32. }
  33. off(event?: string, callback?: (...args: any[]) => void) {
  34. if (!this.events) {
  35. this.events = {}
  36. }
  37. if (event) {
  38. let namespace
  39. ;[event, namespace] = event.split('.')
  40. if (!this.events[event]) {
  41. this.events[event] = []
  42. }
  43. if (callback) {
  44. this.events[event] = this.events[event].filter(
  45. e => e.callback !== callback
  46. )
  47. } else if (!namespace) {
  48. // Clear all listeners for event
  49. delete this.events[event]
  50. } else {
  51. // Clear only namespaced listeners
  52. this.events[event] = this.events[event].filter(
  53. e => e.namespace !== namespace
  54. )
  55. }
  56. } else {
  57. // Remove all listeners
  58. this.events = {}
  59. }
  60. }
  61. trigger(event: string, ...args: any[]) {
  62. if (!this.events) {
  63. this.events = {}
  64. }
  65. if (this.events[event]) {
  66. this.events[event].forEach(e => e.callback(...args))
  67. }
  68. }
  69. emit(event: string, ...args: any[]) {
  70. this.trigger(event, ...args)
  71. }
  72. }