Как отменить отмененную функцию после ее вызова и до ее выполнения?
Я создаю debounced версию функции с подчеркиванием:
var debouncedThing = _.debounce(thing, 1000);
Как только debouncedThing вызывается...
debouncedThing();
... есть ли способ отменить его, в течение периода ожидания до его фактического выполнения?
Ответы
Ответ 1
Если вы используете последнюю версию lodash, вы можете просто:
// create debounce
const debouncedThing = _.debounce(thing, 1000);
// execute debounce, it will wait one second before executing thing
debouncedThing();
// will cancel the execution of thing if executed before 1 second
debouncedThing.cancel()
Другое решение имеет флаг:
// create the flag
let executeThing = true;
const thing = () => {
// use flag to allow execution cancelling
if (!executeThing) return false;
...
};
// create debounce
const debouncedThing = _.debounce(thing, 1000);
// execute debounce, it will wait one second before executing thing
debouncedThing();
// it will prevent to execute thing content
executeThing = false;
Ответ 2
Что я сделал, используется _.mixin для создания метода _.cancellableDebounce. Это почти идентично оригиналу, за исключением двух новых строк.
_.mixin({
cancellableDebounce: function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
var later = function() {
var last = _.now() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
return function() {
context = this;
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout;
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
// Return timeout so debounced function can be cancelled
result = result || {};
result.timeout = timeout;
return result;
};
}
});
ПРИМЕНЕНИЕ:
var thing = function() {
console.log("hello world");
}
var debouncedThing = _.cancellableDebounce(thing, 1000);
var timeout = debouncedThing().timeout;
clearTimeout(timeout);
Ответ 3
Самый простой способ отменить уже вызванную функцию в период ее дебюта - сделать ее отмененной. На самом деле просто добавьте 3 строки кода и одно условие.
const doTheThingAfterADelay = debounce((filter, abort) => {
if (abort) return
// here goes your code...
}, /*debounce delay*/500)
function onFilterChange(filter) {
let abort = false
if (filter.length < 3) { // your abort condition
abort = true
}
doTheThingAfterADelay(filter, abort) // debounced call
}
Вы отменяете его, вызывая его снова с помощью abort = true
.
Для справки, это ваша классическая функция debounce
, взятая из Underscore
. Он остается неповрежденным в моем примере.
// taken from Underscore.js
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
export function debounce(func, wait, immediate) {
let timeout
return function() {
let context = this, args = arguments
let later = function() {
timeout = null
if (!immediate) func.apply(context, args)
}
let callNow = immediate && !timeout
clearTimeout(timeout)
timeout = setTimeout(later, wait)
if (callNow) func.apply(context, args)
}
}
Ответ 4
Старый, но добавление примечания для всех, кто попадает сюда.
Документы (я смотрю на 1.9.1 прямо сейчас) говорят, что вы должны быть в состоянии сделать:
var fn = () => { console.log('run'); };
var db = _.debounce(fn, 1000);
db();
db.cancel();
Это сделало бы то, что ОП хочет сделать (и то, что я хотел сделать). Это не будет печатать консольное сообщение.
Я никогда не мог заставить это работать. Я посмотрел высоко и низко на .cancel()
как и обещал в документе Underscore, и не могу его найти.
Если вы используете Underscore, используйте опцию флага в принятом ответе Карлоса Руана. Мои требования, к сожалению (на мой взгляд), не позволяют обновить (на мой взгляд) с Underscore до Lodash. Подчеркивание имеет меньшую функциональность, но оно более функционально, чем без него.