javascript 如何在调用去抖函数之后、执行之前取消它?

0h4hbjxa  于 2022-12-10  发布在  Java
关注(0)|答案(5)|浏览(106)

我创建了一个带下划线函数的去反跳版本:

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

一旦被揭穿的东西被称为...

debouncedThing();

...在实际执行之前的等待期间,是否有任何方法可以取消它?

flvlnr44

flvlnr441#

如果您使用的是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;
jgovgodb

jgovgodb2#

旧的,但增加了一个注意到任何人谁到这里。
文档(我现在正在看1.9.1)说您应该能够:

var fn = () => { console.log('run'); };
var db = _.debounce(fn, 1000);
db();
db.cancel();

这将完成OP想做的事情(也是我想做的事情)。它不会打印控制台消息。
我从来没有能够让这个工作。我已经寻找了高和低的.cancel()作为承诺在Underscore文件,我找不到它。
如果您使用Underscore,请使用卡洛斯Ruana的已接受答案中的flag选项。我的要求很遗憾(在我看来)不允许从Underscore升级到Lodash(在我看来)。Underscore的功能较少,但比没有Underscore的功能更多。

yftpprvb

yftpprvb3#

Vanilla js系列,带可拆卸 Package

  • 请注意,此解决方案不需要修改外部debounce函数,甚至不需要使用外部函数。逻辑在wrapepr函数中完成。提供了去抖代码。*

允许在去抖期间取消一个已经被调用的函数的最简单的方法是从一个可取消的回绕中调用它。实际上只需要添加3行代码和一个可选条件。

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
}

您可以使用abort = true再次调用它来取消它。
它的工作方式是清除以前的超时fn,并像往常一样设置一个新的超时fn,但现在使用if (true) return路径。
您也可以从另一个代码手动执行此操作...

doTheThingAfterADelayCancellable(null, true)

...或将其打包并调用cancelBounce()

function cancelBounce() {
  doTheThingAfterADelayCancellable(null, true)
}

作为参考,这是从Underscore中提取的经典debounce函数,在我的示例中保持不变。

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

ybzsozfc4#

我所做的是使用_.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);
tgabmvqs

tgabmvqs5#

对于其他使用React和state hooks的人。将debounce事件 Package 在一个ref中,然后在其他地方访问:

const [textInputValue, setTextInputValue] = React.useState<string>('')
    
const debouncedSearch = React.useRef(
    debounce((textInputValue) => {
        performSearch(textInputValue)
    }, 300),
).current

React.useEffect(() => {
    // cancel any previous debounce action (so that a slower - but later - request doesn't overtake a newer but faster request)
    debouncedSearch.cancel()
    if (textInputValue !== '') {
        debouncedSearch(textInputValue)
    }
}, [textInputValue])

相关问题