UNPKG

async-wrappers

Version:

A set of wrapper functions to perform debouncing, throttling, retrying etc.

81 lines (68 loc) 2.02 kB
import callReduce from './callReduce'; import deferred from './deferred'; /** * Ensure multiple calls to a function will only execute at most once every * `delay` milliseconds. * * The execution will always happens asynchronously. If the delay is `0` then * execution will occur after the current runtime event loop. * * The throttled function returns a promise that resolves to the return value * of `func`. * * By default the arguments to `func` are the latest arguments given to the * throttled function. For custom behaviour pass an `argumentsReducer` * function. * * @param func The function to throttle * @param delay The number of milliseconds between executions. * @param options Debounce options * @return The throttled function * * @category Wrapper */ var throttle = function throttle(func) { var delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 50; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var { reducer, onCancel, maxCalls } = options; var calls = 0; var afterReduce = () => { if (maxCalls) { calls++; if (calls >= maxCalls) { flush(); return; } } // nothing pending so go if (execute.delay < 0) { var elapsed = execute.called > 0 ? Date.now() - execute.called : delay; // call right away or with how much time to go before next call execute.defer(elapsed >= delay ? 0 : delay - elapsed); } }; var [call, runner, reject] = callReduce(func, reducer, undefined, afterReduce); var execute = deferred(() => { calls = 0; runner()(); }); var flush = () => { calls = 0; execute.cancel(); deferred(runner()).defer(0); }; var cancel = reason => { execute.cancel(); if (onCancel) { onCancel(); } reject(reason ? reason : new Error('cancelled')); }; var wrapped = call; wrapped.cancel = cancel; wrapped.flush = flush; return wrapped; }; export default throttle;