UNPKG

hd-utils

Version:

A handy utils for modern JS developers

69 lines (68 loc) 2.81 kB
import isObject from '../validation/isObject'; import debounce from './debounce'; /** * Creates a throttled function that only invokes `func` at most once per * every `wait` milliseconds (or once per browser frame). The throttled function * comes with a `cancel` method to cancel delayed `func` invocations and a * `flush` method to immediately invoke them. Provide `options` to indicate * whether `func` should be invoked on the leading and/or trailing edge of the * `wait` timeout. The `func` is invoked with the last arguments provided to the * throttled function. Subsequent calls to the throttled function return the * result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is * invoked on the trailing edge of the timeout only if the throttled function * is invoked more than once during the `wait` timeout. * * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred * until the next tick, similar to `setTimeout` with a timeout of `0`. * * If `wait` is omitted in an environment with `requestAnimationFrame`, `func` * invocation will be deferred until the next frame is drawn (typically about * 16ms). * * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `throttle` and `debounce`. * * @since 0.1.0 * @category Function * @param {Function} func The function to throttle. * @param {number} [wait=0] * The number of milliseconds to throttle invocations to; if omitted, * `requestAnimationFrame` is used (if available). * @param {Object} [options={}] The options object. * @param {boolean} [options.leading=true] * Specify invoking on the leading edge of the timeout. * @param {boolean} [options.trailing=true] * Specify invoking on the trailing edge of the timeout. * @returns {Function} Returns the new throttled function. * @example * // Avoid excessively updating the position while scrolling. * const throttled = throttle(() => { * console.log('Scroll event handler'); * }, 100); * window.addEventListener('scroll', throttled); * // Later, you can cancel the throttled function * throttled.cancel(); * // Or flush the last invocation * throttled.flush(); * */ function throttle(func, wait = 200, options) { let leading = true; let trailing = true; if (typeof func !== 'function') { console.error('Expected a function'); return () => { }; } if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } return debounce(func, wait, { leading, trailing, maxWait: wait, }); } export default throttle;