Portfolio: MultipleEventCalmer class

By

Some events (such as scroll, resize, etc.) can fire often. If there handlers do a non-trivial amount of work, calling them repeatedly for each event can cause significant performance issues. This class, implementing the IEventCalmer interface, takes an array of event names and creates an EventCalmer for each one. They can then be managed as a group.

import { EventCalmer } from "./EventCalmer";
import { SharedState } from "./SharedState";
import type { EventCalmerOptions, IEventCalmer } from "./types";

/**
 * A class that manages multiple `EventCalmer` instances.
 *
 * This class is useful when you need to handle multiple events with the same
 * options. It ensures that the handler isn't called again if it's already
 * running from a different EventCalmer instance in the group.
 *
 * @example
 * ```typescript
 * const eventNames = ['event1', 'event2', 'event3'];
 * const options = { minimum_interval: 10, callback: () => console.log('Event calmed') };
 * const calmer = new MultipleEventCalmer(eventNames, options, true);
 * calmer.start();
 * ```
 *
 * @class MultipleEventCalmer
 * @property {EventCalmer[]} #calmers - An array of `EventCalmer` instances.
 *
 * @constructor
 * @param {string[]} event_names - An array of event names to be calmed.
 * @param {Omit<EventCalmerOptions, 'event'>} options - Options for each `EventCalmer` instance, excluding the event name.
 * @param {boolean} [fire_on_start=false] - Whether to fire the event on start.
 *
 * @method start - Starts all `EventCalmer` instances.
 * @method stop - Stops all `EventCalmer` instances.
 * @method trigger - Manually triggers the first `EventCalmer` instance.
 */
export class MultipleEventCalmer implements IEventCalmer {
  // #region Properties (2)

  calmers: EventCalmer[];
  shared_state = new SharedState();

  // #endregion Properties (2)

  // #region Constructors (1)

  /**
   * Creates an instance of MultipleEventCalmer.
   *
   * @param event_names - An array of event names to be calmed.
   * @param options - Options for the EventCalmer instances, excluding the 'event' property.
   * @param fire_on_start - A boolean indicating whether to fire the event on start. Defaults to false.
   */
  constructor(
    event_names: string[],
    options: Omit<EventCalmerOptions, "event">,
    fire_on_start: boolean = false
  ) {
    this.calmers = event_names.map(
      (event) =>
        new EventCalmer({ ...options, event }, fire_on_start)
    );
    this.shared_state.handlerRunning = false;
    this.calmers.forEach((calmer) => (calmer.shared_state = this.shared_state));
  }

  // #endregion Constructors (1)

  // #region Public Methods (3)

  /**
   * Starts all the event calmers in the `calmers` array.
   */
  listen(): void {
    this.calmers.forEach((calmer) => calmer.listen());
  }

  /**
   * Manually triggers the first event calmer in the `calmers` array.
   */
  trigger(): void {
    if(this.calmers.length > 0) this.calmers[0].trigger();
  }

  /**
   * Stops all the event calmers in the `calmers` array.
   */
  unlisten(): void {
    this.calmers.forEach((calmer) => calmer.unlisten());
  }

  // #endregion Public Methods (3)
}