73 lines
1.7 KiB
JavaScript
73 lines
1.7 KiB
JavaScript
export function throttle(delay, callback, options) {
|
|
const {
|
|
noTrailing = false,
|
|
noLeading = false,
|
|
debounceMode = undefined
|
|
} = options || {};
|
|
|
|
let timeoutID;
|
|
let cancelled = false;
|
|
let lastExec = 0;
|
|
|
|
function clearExistingTimeout() {
|
|
if (timeoutID) {
|
|
clearTimeout(timeoutID);
|
|
}
|
|
}
|
|
|
|
function cancel(options) {
|
|
const {upcomingOnly = false} = options || {};
|
|
clearExistingTimeout();
|
|
cancelled = !upcomingOnly;
|
|
}
|
|
|
|
function wrapper(...arguments_) {
|
|
let self = this;
|
|
let elapsed = Date.now() - lastExec;
|
|
|
|
if (cancelled) {
|
|
return;
|
|
}
|
|
|
|
function exec() {
|
|
lastExec = Date.now();
|
|
callback.apply(self, arguments_);
|
|
}
|
|
|
|
function clear() {
|
|
timeoutID = undefined;
|
|
}
|
|
|
|
if (!noLeading && debounceMode && !timeoutID) {
|
|
exec();
|
|
}
|
|
|
|
clearExistingTimeout();
|
|
|
|
if (debounceMode === undefined && elapsed > delay) {
|
|
if (noLeading) {
|
|
lastExec = Date.now();
|
|
if (!noTrailing) {
|
|
timeoutID = setTimeout(debounceMode ? clear : exec, delay);
|
|
}
|
|
} else {
|
|
exec();
|
|
}
|
|
} else if (noTrailing !== true) {
|
|
timeoutID = setTimeout(
|
|
debounceMode ? clear : exec,
|
|
debounceMode === undefined ? delay - elapsed : delay
|
|
);
|
|
}
|
|
}
|
|
|
|
wrapper.cancel = cancel;
|
|
return wrapper;
|
|
}
|
|
|
|
|
|
export function debounce(delay, callback, options) {
|
|
const {atBegin = false} = options || {};
|
|
return throttle(delay, callback, {debounceMode: atBegin !== false});
|
|
}
|