blob: f236ec349ec48c2eccdcf5f102b2614aa6e40131 [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001/**
2 * Throttling enforces a maximum number of times a function can be called over time.
3 *
4 * @param callback the function to throttle
5 * @param delay optional delay, default to 1000/60ms
6 * @param context optional context of this, default to global window
7 * @returns {Function} reference to immediate and cancel functions
8 * @see https://developer.mozilla.org/en-US/docs/Web/Events/resize#Example
9 * @see https://gist.github.com/yoavniran/d1d33f278bb7744d55c3
10 * @see https://github.com/pelotoncycle/frame-throttle
11 * @see https://github.com/jeromedecoster/raf-funcs
12 */
13const MIN_DELAY = 1000/60;
14
15const throttleFunction = (callback, delay=MIN_DELAY, context) => {
16
17 if(delay < MIN_DELAY) {
18 delay = MIN_DELAY;
19 }
20
21 if (!context) {
22 context = this || window;
23 }
24
25 let next = null;
26 let start = 0;
27
28 return (...args) => {
29
30 const cancel = () => {
31 if(next !== null) {
32 window.cancelAnimationFrame(next);
33 next = null;
34 }
35 };
36
37 const execute = () => {
38 cancel();
39 return Reflect.apply(callback, context, args);
40 };
41
42 const later = () => {
43 if (delay - (Date.now() - start) <= 0) {
44 return execute();
45 }
46 next = window.requestAnimationFrame(later);
47 };
48
49 if(next === null) {
50 start = Date.now();
51 next = window.requestAnimationFrame(later);
52 }
53
54 return {
55 cancel: () => cancel(),
56 immediate: () => execute()
57 };
58 };
59};
60
61export default throttleFunction;