Javascript 如何在被调用之后和执行之前取消取消取消公告的函数?

Javascript 如何在被调用之后和执行之前取消取消取消公告的函数?,javascript,underscore.js,Javascript,Underscore.js,我创建了一个带下划线的函数的取消公告版本: var debouncedThing = _.debounce(thing, 1000); 一旦脱口而出,事情就叫做 debouncedThing(); …在它实际执行之前的等待期间,有什么方法可以取消它吗?我所做的是使用.mixin创建一个.cancelabledebounce方法。除了两条新的线路外,它几乎和原来的一样 _.mixin({ cancellableDebounce: function(func, wait, immedia

我创建了一个带下划线的函数的取消公告版本:

var debouncedThing = _.debounce(thing, 1000);
一旦脱口而出,事情就叫做

debouncedThing();

…在它实际执行之前的等待期间,有什么方法可以取消它吗?

我所做的是使用.mixin创建一个.cancelabledebounce方法。除了两条新的线路外,它几乎和原来的一样

_.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;
        };
    }
});
带可取消包装的Vanilla js变体 请注意,此解决方案不要求您修改外部
去盎司
函数,甚至不需要使用外部函数。该逻辑在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
}
…或将其包装并使用
cancelBounce()调用

作为参考,这是您的经典
去盎司
函数,取自
下划线
。在我的例子中,它保持不变

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

如果使用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;

旧的,但为任何到这里的人添加了一个便条

文档(我现在正在看1.9.1)说您应该能够做到:

var fn = () => { console.log('run'); };
var db = _.debounce(fn, 1000);
db();
db.cancel();
这将完成OP想要做的事情(以及我想要做的事情)。它不会打印控制台消息

我从来没能让它工作。我到处寻找下划线文档中承诺的
.cancel()
,但我找不到它


如果使用下划线,请在Carlos Ruana接受的答案中使用标志选项。遗憾的是(在我看来)我的需求不允许(在我看来)从下划线升级到Lodash。下划线的功能较少,但功能性更强。

该问题的可能重复之处尚不清楚。我的是具体的。这个问题并没有回答我的问题。当然,你可以实现你自己版本的debouncer,它会以某种方式暴露
超时
或清除超时的函数。这回答得很好,我希望你删除了否决票
// 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;
var fn = () => { console.log('run'); };
var db = _.debounce(fn, 1000);
db();
db.cancel();