| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- import requestAnimationFrame from '../shims/requestAnimationFrame.js';
- // Defines minimum timeout before adding a trailing call.
- const trailingTimeout = 2;
- /**
- * Creates a wrapper function which ensures that provided callback will be
- * invoked only once during the specified delay period.
- *
- * @param {Function} callback - Function to be invoked after the delay period.
- * @param {number} delay - Delay after which to invoke callback.
- * @returns {Function}
- */
- export default function (callback, delay) {
- let leadingCall = false,
- trailingCall = false,
- lastCallTime = 0;
- /**
- * Invokes the original callback function and schedules new invocation if
- * the "proxy" was called during current request.
- *
- * @returns {void}
- */
- function resolvePending() {
- if (leadingCall) {
- leadingCall = false;
- callback();
- }
- if (trailingCall) {
- proxy();
- }
- }
- /**
- * Callback invoked after the specified delay. It will further postpone
- * invocation of the original function delegating it to the
- * requestAnimationFrame.
- *
- * @returns {void}
- */
- function timeoutCallback() {
- requestAnimationFrame(resolvePending);
- }
- /**
- * Schedules invocation of the original function.
- *
- * @returns {void}
- */
- function proxy() {
- const timeStamp = Date.now();
- if (leadingCall) {
- // Reject immediately following calls.
- if (timeStamp - lastCallTime < trailingTimeout) {
- return;
- }
- // Schedule new call to be in invoked when the pending one is resolved.
- // This is important for "transitions" which never actually start
- // immediately so there is a chance that we might miss one if change
- // happens amids the pending invocation.
- trailingCall = true;
- } else {
- leadingCall = true;
- trailingCall = false;
- setTimeout(timeoutCallback, delay);
- }
- lastCallTime = timeStamp;
- }
- return proxy;
- }
|