events.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * Events allow for applications to use the observer pattern, which
  3. * allows subscribing and publishing events, outside the normal
  4. * execution paths.
  5. *
  6. * @_section api/utils/events:Events [about-events]
  7. */
  8. import { defineProperties } from "./properties.js";
  9. /**
  10. * A callback function called when a an event is triggered.
  11. */
  12. export type Listener = (...args: Array<any>) => void;
  13. /**
  14. * An **EventEmitterable** behaves similar to an EventEmitter
  15. * except provides async access to its methods.
  16. *
  17. * An EventEmitter implements the observer pattern.
  18. */
  19. export interface EventEmitterable<T> {
  20. /**
  21. * Registers a %%listener%% that is called whenever the
  22. * %%event%% occurs until unregistered.
  23. */
  24. on(event: T, listener: Listener): Promise<this>;
  25. /**
  26. * Registers a %%listener%% that is called the next time
  27. * %%event%% occurs.
  28. */
  29. once(event: T, listener: Listener): Promise<this>;
  30. /**
  31. * Triggers each listener for %%event%% with the %%args%%.
  32. */
  33. emit(event: T, ...args: Array<any>): Promise<boolean>;
  34. /**
  35. * Resolves to the number of listeners for %%event%%.
  36. */
  37. listenerCount(event?: T): Promise<number>;
  38. /**
  39. * Resolves to the listeners for %%event%%.
  40. */
  41. listeners(event?: T): Promise<Array<Listener>>;
  42. /**
  43. * Unregister the %%listener%% for %%event%%. If %%listener%%
  44. * is unspecified, all listeners are unregistered.
  45. */
  46. off(event: T, listener?: Listener): Promise<this>;
  47. /**
  48. * Unregister all listeners for %%event%%.
  49. */
  50. removeAllListeners(event?: T): Promise<this>;
  51. /**
  52. * Alias for [[on]].
  53. */
  54. addListener(event: T, listener: Listener): Promise<this>;
  55. /**
  56. * Alias for [[off]].
  57. */
  58. removeListener(event: T, listener: Listener): Promise<this>;
  59. }
  60. /**
  61. * When an [[EventEmitterable]] triggers a [[Listener]], the
  62. * callback always ahas one additional argument passed, which is
  63. * an **EventPayload**.
  64. */
  65. export class EventPayload<T> {
  66. /**
  67. * The event filter.
  68. */
  69. readonly filter!: T;
  70. /**
  71. * The **EventEmitterable**.
  72. */
  73. readonly emitter!: EventEmitterable<T>;
  74. readonly #listener: null | Listener;
  75. /**
  76. * Create a new **EventPayload** for %%emitter%% with
  77. * the %%listener%% and for %%filter%%.
  78. */
  79. constructor(emitter: EventEmitterable<T>, listener: null | Listener, filter: T) {
  80. this.#listener = listener;
  81. defineProperties<EventPayload<any>>(this, { emitter, filter });
  82. }
  83. /**
  84. * Unregister the triggered listener for future events.
  85. */
  86. async removeListener(): Promise<void> {
  87. if (this.#listener == null) { return; }
  88. await this.emitter.off(this.filter, this.#listener);
  89. }
  90. }