Creo una versión rebotada de una función con guión bajo:
var debouncedThing = _.debounce(thing, 1000);Una vez rebotado, la cosa se llama...
debouncedThing();... ¿hay alguna forma de cancelarlo durante el período de espera antes de que se ejecute realmente?
Si usa la última versión de lodash, simplemente puede 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;Viejo, pero agregando una nota para cualquier otra persona que llegue aquí.
Los documentos (estoy viendo 1.9.1 en este momento) dicen que deberías poder hacer:
var fn = () => { console.log('run'); }; var db = _.debounce(fn, 1000); db(); db.cancel();Esto haría lo que el OP quiere hacer (y lo que yo quería hacer). No imprimiría el mensaje de la consola.
Nunca he sido capaz de hacer que esto funcione. He buscado por todas partes un .cancel() como se prometió en el documento de subrayado y no puedo encontrarlo.
Si está usando el guión bajo, use la opción de bandera en la respuesta aceptada por Carlos Ruana. Lamentablemente, mis requisitos (en mi opinión) no permiten una actualización (en mi opinión) de Underscore a Lodash. El guión bajo tiene menos funcionalidad pero es más funcional que sin él.
Tenga en cuenta que esta solución no requiere que modifique una función de debounce externa o incluso que use una externa. La lógica se realiza en una función wrapepr. Código de rebote proporcionado.
La forma más fácil de permitir cancelar una función ya llamada dentro de su período de rebote es llamarla desde una envoltura cancelable. Realmente solo agregue 3 líneas de código y una condición opcional.
const doTheThingAfterADelayCancellable = debounce((filter, abort) => { if (abort) return // here goes your code... // or call the original function here }, /*debounce delay*/500) function onFilterChange(filter) { let abort = false if (filter.length < 3) { // your abort condition abort = true } // doTheThingAfterADelay(filter) // before doTheThingAfterADelayCancellable(filter, abort) // new wrapped debounced call } Lo cancelas llamándolo de nuevo con abort = true .
La forma en que funciona es que borra el tiempo de espera anterior fn y establece uno nuevo como siempre lo hace, pero ahora con la ruta de if (true) return .
También puedes hacerlo manualmente desde otro código...
doTheThingAfterADelayCancellable(null, true) ...o envuélvelo y llama con cancelBounce()
function cancelBounce() { doTheThingAfterADelayCancellable(null, true) }Como referencia, esta es su función de
debounceclásica tomada deUnderscore. 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) } }