Debounce for 500ms if True else 执行

Debounce for 500ms if True else execute

剧透;我是 jQuery/Javascript.

的新手

我有一个布尔字段 CheckMe 和一个输入字段 textField

如果 textField 为空,则 CheckMe 不应显示,否则应显示(这意味着如果从非空变为空 CheckMe 应立即再次隐藏)。我想解析一个延迟,比如 500 毫秒,即如果 text 不为空并且在最后一次按键

500 毫秒后显示 CheckMe

我已经尝试使用 this SO 答案中的去抖功能(参见下面我的实现),但问题是,CheckMe 也是在 textField 500 毫秒后首次隐藏空着

<script type="text/javascript">
  function debounce(fn, duration) {
  var timer;
  return function(){
    clearTimeout(timer);
    timer = setTimeout(fn, duration);
  }
}

$(document).ready(function () {
    const textField= $("#textField");
    const CheckMe= $("#CheckMe");
    CheckMe.hide();

    textField.on("input", debounce(()=> {
      if (textField.val()) {
        CheckMe.show();
      } else {
        CheckMe.hide();
      }
    },500));
});
</script>

但是当我清除 textField.

时,它会在 500 毫秒后删除 checkMe

我已经尝试将去抖移到 True 语句中,即

...
   textField.on("input", function() {
      if (textField.val()) {
        debounce(function(){CheckMe.show();},500)
      
      } else {

        CheckMe.hide();
      }
}

但在任何时候都不显示 CheckMe

if () { debouce(()={}); } else { immediate(); } 尝试失败的原因是事件处理程序如何存储函数以及 debounce 如何存储其计时器。

当你运行 .on("input", function() { }) 将函数定义存储在事件处理程序中,准备运行。然而,对于去抖动,这不是正在做的事情,而是:

.on("input", function())

没有函数定义 - 它调用函数本身,恰好return另一个函数在事件运行s时被调用。

这就是为什么有这么多关于 SO 的问题,比如“我的代码 运行 当我执行 .on("input", myfunction()) 时,它应该是 .on("input", myfunction)

所以每个事件设置一个函数(去抖动)运行s 一次 - 不是每个 input 事件触发一次,而是设置时只触发一次事件。所以只有一个 var timer 的实例,它都包含在 debounce 函数中。然后事件触发调用 return function() 中的代码,该代码已经在其外部范围(先前的去抖动调用)中定义了 var timer

如果您使用第二个输入再次调用 debounce $("#secondInp").on("input", debounce(() => ...,您将获得该函数的第二个实例及其自己的变量(因此它们不会在 inp1 和 inp2 之间发生冲突)。

所以你可以看到,如果你把它放在事件处理程序中(在 if 中),你每次都会调用 new 去抖动(不是同一个)。

你的尝试没有做任何事情,因为你的代码 debounce(function(){CheckMe.show();},500) 只是 return 函数 - 所以你需要做

debounce(function(){CheckMe.show();},500)();`

但即便如此也不会像 那样工作 每次调用它(每个事件)你都会得到一个新的去抖动函数实例和一个新的 var timer 实例.


您可以使用两个事件。在每个事件中检查是否应显示“检查我”。

debounced 将在 500 毫秒后 运行 而未去抖动的将立即 运行。

function debounce(fn, duration) {
  var timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(fn, duration);
  }
}


$(document).ready(function() {

  const textField = $("#textField");
  const checkMe = $("#checkMe");
  checkMe.hide();

  textField.on("input", debounce(() => {
    if (textField.val()) {
      checkMe.show();
    }
  }, 500));

  textField.on("input", () => {
    if (!textField.val()) {
      checkMe.hide();
    }
  });
});
#checkMe { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="textField" type="text">
<div id='checkMe'>^-- check this</div>


is it possible to keep it in a single if-else

鉴于上面的解释,不可能按原样使用您的 debounce 函数;因为 return function() { }timer 的单个实例。关键是 timer.

的单个实例

没有去抖动,这可以在一个函数中实现,使用定时器的外部变量,但每次都需要重复去抖动代码(例如,第二次input) - 只是 clearTimeout 和 setTimeout 代码 - 所以不多 - 成为问题的是“全局”/外部范围变量。

$(document).ready(function() {

  var textFieldTimer = null;
  
  const textField = $("#textField");
  const checkMe = $("#checkMe");
  checkMe.hide();

  textField.on("input", () => {
    if (textField.val()) {
      clearTimeout(textFieldTimer);
      textFieldTimer = setTimeout(() => checkMe.show(), 500);
    }
    else {
      checkMe.hide();
    }
  });
});
#checkMe { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="textField" type="text">
<div id='checkMe'>^-- check this</div>


那么我们如何同时使用:可重用函数和事件处理程序中的 if

通过在元素本身上存储 timer 单个实例 - 在下面的代码中使用 .data(),但任何存储单个实例的方法每个元素也将起作用。

这是一个示例,使用具有 if 的单个事件并针对第二个输入重复以显示其工作原理。

function debounce2(fn, duration)
{
    var timer = $(this).data("timer");
    clearTimeout(timer);
    $(this).data("timer", setTimeout(fn, duration));
}

$(document).ready(function() {

  $("#checkMe, #checkMe2").hide();

  $("#textField, #textField2").on("input", function() {
    if ($(this).val()) {
      debounce2.call(textField, () => $("#checkMe").show(), 500);
    }
    else {
      $("#checkMe").hide();
    }
  });



  // second input confirming `timer` is per element.
  
  $("#textField2").on("input", function() {
    if ($(this).val()) {
      debounce2.call(textField, () => $("#checkMe2").show(), 500);
    }
    else {
      $("#checkMe2").hide();
    }
  });  
});
#checkMe, #checkMe2 { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="textField" type="text">
<div id='checkMe'>^-- check this</div>
<hr/>
<input id="textField2" type="text">
<div id='checkMe2'>^-- check this</div>