105 lines
3.2 KiB
JavaScript
105 lines
3.2 KiB
JavaScript
"use strict";
|
|
const FUNC_ERROR_TEXT = "Expected a function";
|
|
function throttle(func, wait, options) {
|
|
let leading = true, trailing = true;
|
|
if (typeof func != "function") {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
if (options && isObject(options)) {
|
|
leading = "leading" in options ? !!options.leading : leading;
|
|
trailing = "trailing" in options ? !!options.trailing : trailing;
|
|
}
|
|
return debounce(func, wait, {
|
|
leading,
|
|
maxWait: wait,
|
|
trailing
|
|
});
|
|
}
|
|
function debounce(func, wait, options) {
|
|
let lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
|
|
if (typeof func != "function") {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
wait = wait || 0;
|
|
if (options && isObject(options)) {
|
|
leading = !!options.leading;
|
|
maxing = "maxWait" in options;
|
|
maxWait = maxing ? Math.max(options.maxWait || 0, wait) : maxWait;
|
|
trailing = "trailing" in options ? !!options.trailing : trailing;
|
|
}
|
|
function invokeFunc(time) {
|
|
const args = lastArgs, thisArg = lastThis;
|
|
lastArgs = lastThis = void 0;
|
|
lastInvokeTime = time;
|
|
result = func.apply(thisArg, args);
|
|
return result;
|
|
}
|
|
function leadingEdge(time) {
|
|
lastInvokeTime = time;
|
|
timerId = setTimeout(timerExpired, wait);
|
|
return leading ? invokeFunc(time) : result;
|
|
}
|
|
function remainingWait(time) {
|
|
const timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall;
|
|
return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
|
|
}
|
|
function shouldInvoke(time) {
|
|
const timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
|
|
return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
|
|
}
|
|
function timerExpired() {
|
|
const time = Date.now();
|
|
if (shouldInvoke(time)) {
|
|
return trailingEdge(time);
|
|
}
|
|
timerId = setTimeout(timerExpired, remainingWait(time));
|
|
}
|
|
function trailingEdge(time) {
|
|
timerId = void 0;
|
|
if (trailing && lastArgs) {
|
|
return invokeFunc(time);
|
|
}
|
|
lastArgs = lastThis = void 0;
|
|
return result;
|
|
}
|
|
function cancel() {
|
|
if (timerId !== void 0) {
|
|
clearTimeout(timerId);
|
|
}
|
|
lastInvokeTime = 0;
|
|
lastArgs = lastCallTime = lastThis = timerId = void 0;
|
|
}
|
|
function flush() {
|
|
return timerId === void 0 ? result : trailingEdge(Date.now());
|
|
}
|
|
function debounced() {
|
|
const time = Date.now(), isInvoking = shouldInvoke(time);
|
|
lastArgs = arguments;
|
|
lastThis = this;
|
|
lastCallTime = time;
|
|
if (isInvoking) {
|
|
if (timerId === void 0) {
|
|
return leadingEdge(lastCallTime);
|
|
}
|
|
if (maxing) {
|
|
clearTimeout(timerId);
|
|
timerId = setTimeout(timerExpired, wait);
|
|
return invokeFunc(lastCallTime);
|
|
}
|
|
}
|
|
if (timerId === void 0) {
|
|
timerId = setTimeout(timerExpired, wait);
|
|
}
|
|
return result;
|
|
}
|
|
debounced.cancel = cancel;
|
|
debounced.flush = flush;
|
|
return debounced;
|
|
}
|
|
function isObject(value) {
|
|
const type = typeof value;
|
|
return value != null && (type == "object" || type == "function");
|
|
}
|
|
exports.debounce = debounce;
|
|
exports.throttle = throttle;
|