123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- /* @see https://github.com/lodash/lodash/blob/master/debounce.js */
- /* @see https://www.lodashjs.com/docs/lodash.debounce */
- function debounce(func, wait, options) {
- var lastArgs,
- lastThis,
- maxWait,
- result,
- timerId,
- lastCallTime;
- var lastInvokeTime = 0;
- var leading = false;
- var maxing = false;
- var trailing = true;
- if (typeof func !== 'function') {
- throw new TypeError('Expected a function')
- }
- wait = +wait || 0;
- if (isObject(options)) {
- leading = !!options.leading;
- maxing = 'maxWait' in options;
- maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : wait;
- trailing = 'trailing' in options ? !!options.trailing : trailing
- }
- function isObject(value) {
- var type = typeof value;
- return value != null && (type === 'object' || type === 'function')
- }
- function invokeFunc(time) {
- var args = lastArgs;
- var thisArg = lastThis;
- lastArgs = lastThis = undefined;
- lastInvokeTime = time;
- result = func.apply(thisArg, args);
- return result
- }
- function startTimer(pendingFunc, wait) {
- return setTimeout(pendingFunc, wait)
- }
- function cancelTimer(id) {
- clearTimeout(id)
- }
- function leadingEdge(time) {
- // Reset any `maxWait` timer.
- lastInvokeTime = time;
- // Start the timer for the trailing edge.
- timerId = startTimer(timerExpired, wait);
- // Invoke the leading edge.
- return leading ? invokeFunc(time) : result
- }
- function remainingWait(time) {
- var timeSinceLastCall = time - lastCallTime;
- var timeSinceLastInvoke = time - lastInvokeTime;
- var timeWaiting = wait - timeSinceLastCall;
- return maxing
- ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
- : timeWaiting
- }
- function shouldInvoke(time) {
- var timeSinceLastCall = time - lastCallTime;
- var timeSinceLastInvoke = time - lastInvokeTime;
- // Either this is the first call, activity has stopped and we're at the
- // trailing edge, the system time has gone backwards and we're treating
- // it as the trailing edge, or we've hit the `maxWait` limit.
- return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
- (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait))
- }
- function timerExpired() {
- var time = Date.now();
- if (shouldInvoke(time)) {
- return trailingEdge(time)
- }
- // Restart the timer.
- timerId = startTimer(timerExpired, remainingWait(time))
- }
- function trailingEdge(time) {
- timerId = undefined;
- // Only invoke if we have `lastArgs` which means `func` has been
- // debounced at least once.
- if (trailing && lastArgs) {
- return invokeFunc(time)
- }
- lastArgs = lastThis = undefined;
- return result
- }
- function cancel() {
- if (timerId !== undefined) {
- cancelTimer(timerId)
- }
- lastInvokeTime = 0;
- lastArgs = lastCallTime = lastThis = timerId = undefined
- }
- function flush() {
- return timerId === undefined ? result : trailingEdge(Date.now())
- }
- function pending() {
- return timerId !== undefined
- }
- function debounced() {
- var time = Date.now();
- var isInvoking = shouldInvoke(time);
- lastArgs = arguments;
- lastThis = this;
- lastCallTime = time;
- if (isInvoking) {
- if (timerId === undefined) {
- return leadingEdge(lastCallTime)
- }
- if (maxing) {
- // Handle invocations in a tight loop.
- timerId = startTimer(timerExpired, wait);
- return invokeFunc(lastCallTime)
- }
- }
- if (timerId === undefined) {
- timerId = startTimer(timerExpired, wait)
- }
- return result
- }
- debounced.cancel = cancel;
- debounced.flush = flush;
- debounced.pending = pending;
- return debounced
- }
- export default debounce
|