javascript underscore.js

javascript - ¿Cómo cancelar una función de rebote después de que se llama y antes de que se ejecute?



underscore.js (3)

La forma más fácil de cancelar una función ya llamada dentro de su período de rebote es hacerlo cancelable. Realmente solo agregue 3 líneas de código y una condición.

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 }

Lo cancelas llamándolo de nuevo con abort = true .

Para referencia, esta es su función de debounce clásica tomada desde el debounce bajo. Permanece intacto en mi ejemplo.

// 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) } }

Creo una versión con rebote de una función con un guión bajo:

var debouncedThing = _.debounce(thing, 1000);

Una vez que se llama debouncThing se llama ...

debouncedThing();

... ¿hay alguna forma de cancelarlo, durante el período de espera antes de que se ejecute?


Lo que he hecho es usar _.mixin para crear un método _.cancellableDebounce. Es casi idéntico al original, excepto por dos nuevas líneas.

_.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; }; } });

USO:

var thing = function() { console.log("hello world"); } var debouncedThing = _.cancellableDebounce(thing, 1000); var timeout = debouncedThing().timeout; clearTimeout(timeout);


Si usas la última versión de lodash puedes simplemente hacer:

// 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()

Otra solución es con una bandera:

// 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;