/ shared / components / src / utils / throttle.ts
throttle.ts
 1  /* eslint-disable import/prefer-default-export */
 2  /**
 3   * @name throttle
 4   * @description
 5   * Creates a throttled function that only invokes func at most once per every limit time (ms).
 6   *
 7   * *NOTE: this does not capture or recall all functions that were triggered.
 8   * This will drop function calls that happen during the throttle time*
 9   * @param limit - time to wait between calls in ms
10   * @example
11   * Normal event
12   * event      | |   |   |
13   * time     ----------------
14   * callback   | |   |   |
15   *
16   * Throttled event [300ms]
17   * event    |   |   |    |
18   * time     ----------------
19   * callback |      |      |
20   *             [300]  [300]
21   */
22  
23  export function throttle<T extends []>(
24      func: (..._: T) => unknown,
25      limit: number,
26  ): (..._: T) => void {
27      let lastTimeoutId;
28      let lastCallTime: number;
29  
30      return function throttled(...args) {
31          const nextCall = () => {
32              func.apply(this, args);
33              lastCallTime = Date.now();
34          };
35  
36          if (!lastCallTime) {
37              nextCall();
38          } else {
39              clearTimeout(lastTimeoutId);
40              const timeBetweenCalls = Date.now() - lastCallTime;
41              const waitTime = Math.max(0, limit - timeBetweenCalls);
42              lastTimeoutId = setTimeout(() => {
43                  if (timeBetweenCalls >= limit) {
44                      nextCall();
45                  }
46              }, waitTime);
47          }
48      };
49  }