UNPKG

@gravityforms/utils

Version:
113 lines (93 loc) 3.25 kB
import mimicFn from '../data/mimic-fn'; /** * @module debounce * @description Returns a debounced function that delays calling the input function until after wait milliseconds * have elapsed since the last time the debounced function was called. * It comes with a .cancel() method to cancel any scheduled input function calls. * * @since 1.0.0 * * @param {Function} inputFunction Function to debounce. * @param {object} options { * {number} wait Time in milliseconds to wait until the input function is called, default: 0. * {number} maxWait The maximum time the input function is allowed to be delayed before it's invoked. This can be used to limit the number of calls handled in a constant stream. For example, a media player sending updates every few milliseconds but wants to be handled only once a second, default: infinity. * {boolean} before Trigger the function on the leading edge of the wait interval. For example, can be useful for preventing accidental double-clicks on a "submit" button from firing a second time, default: false * {boolean} after Trigger the function on the trailing edge of the wait interval, default: true * } * * @requires mimicFn * * @return {Function} The debounced function. * * @example * import { debounce } from "@gravityforms/utils"; * * function Example() { * // do something on resize * } * * window.addEventListener( 'resize', debounce( Example, { wait: 400 } ) ); * */ export default function debounce( inputFunction, options = {} ) { if ( typeof inputFunction !== 'function' ) { throw new TypeError( `Expected the first argument to be a function, got \`${ typeof inputFunction }\`` ); } const { wait = 0, maxWait = Number.Infinity, before = false, after = true, } = options; if ( ! before && ! after ) { throw new Error( 'Both `before` and `after` are false, function wouldn\'t be called.' ); } let timeout; let maxTimeout; let result; const debouncedFunction = function( ...arguments_ ) { const context = this; const later = () => { timeout = undefined; if ( maxTimeout ) { clearTimeout( maxTimeout ); maxTimeout = undefined; } if ( after ) { result = inputFunction.apply( context, arguments_ ); } }; const maxLater = () => { maxTimeout = undefined; if ( timeout ) { clearTimeout( timeout ); timeout = undefined; } if ( after ) { result = inputFunction.apply( context, arguments_ ); } }; const shouldCallNow = before && ! timeout; clearTimeout( timeout ); timeout = setTimeout( later, wait ); if ( maxWait > 0 && maxWait !== Number.Infinity && ! maxTimeout ) { maxTimeout = setTimeout( maxLater, maxWait ); } if ( shouldCallNow ) { result = inputFunction.apply( context, arguments_ ); } return result; }; mimicFn( debouncedFunction, inputFunction ); debouncedFunction.cancel = () => { if ( timeout ) { clearTimeout( timeout ); timeout = undefined; } if ( maxTimeout ) { clearTimeout( maxTimeout ); maxTimeout = undefined; } }; return debouncedFunction; }