【问题标题】:How to stop a Javascript function call within setTimeout after it has been fired?触发后如何在 setTimeout 内停止 Javascript 函数调用?
【发布时间】:2015-11-20 06:12:51
【问题描述】:

我有一个侦听“mouseenter”事件的 div,并在 5 秒后触发 libraryFunction(我无法编辑)(使用 setTimeout 实现)。

但是,如果用户在这 5 秒内点击了 div,则 setTimeout 应该被取消,并且该函数不应该运行(通过 clearTimeout 实现)。点击也会移除 libraryFunction 所依赖的元素。

目前我有以下代码:

var timeoutVar;
$("#mydiv").on("mouseenter", function(event) {
    timeoutVar =  setTimeout(function() {
        runLibraryFunction(object);
    }, 5000);
});

$("#mydiv").on("click", function(event) {
    clearTimeout(timeoutVar);
    removeObject(object);
});

这在大多数情况下都有效,但是,在 5 秒后单击 div 并且在执行 runLibraryFunction() 时存在边缘情况。 因为“click”事件会移除 runLibraryFunction 需要的对象,而这发生在 runLibraryFunction 运行时,runLibraryFunction 会抛出错误。

有没有办法在 runLibraryFunction() 调用被触发后停止它?

【问题讨论】:

  • 对象点击后需要移除什么?
  • 这看起来像一个 XY 问题,您在完成后在 runLibraryFunction 函数的末尾删除 removeObject() 怎么样?
  • 我建议,在超时触发点击事件中,而不是直接调用函数。这将使代码流更加清晰。同样,一旦点击被触发,您可以设置像 processing 这样的标志,并且仅在其 false 状态下调用函数。
  • 另外,您可以在setTimeout函数中runLibraryFunction之前的.off()click事件。这样如果它开始运行库函数,那么就没有回头路了。只会有两种情况:在 5 秒过去之前点击 - 对象已被移除; 5 秒过去了 - 库函数将运行并完成执行。
  • 这闻起来像是设计缺陷,需要检测或避免删除。

标签: javascript jquery


【解决方案1】:

棘手但会工作

timeoutVar =  setTimeout(function() {
        setTimeout(function(){ 
            if(object)
            runLibraryFunction(object);
        },1000);
    }, 5000);

保持不变。

或使用立即调用的函数

timeoutVar =  setTimeout(function() {
                  (function(object){ 
                      runLibraryFunction(object);
                   })(object);
              }, 5000);

现在对象将始终可以访问

【讨论】:

  • 使用嵌套超时只会添加大约 1-1.5 秒的缓冲区。如果处理时间超过此,问题将持续存在。直接调用函数和使用IIFE也有区别吗?
  • 是的,当然 IIFE 会让 object 始终在 runLibraryFunction 的范围内
  • 会添加一个简单的 if 条件不能解决吗?我想添加一个标志会比使用 IIFE 或嵌套超时更好的方法
【解决方案2】:

您可以在启动库函数时向对象添加一个属性,从而防止它被删除,例如:

var timeoutVar;
$("#mydiv").on("mouseenter", function(event) {
    timeoutVar =  setTimeout(function() {
        object.keepmealive=1;
        runLibraryFunction(object);
        if (object) delete object.keepmealive;
    }, 5000);
});

$("#mydiv").on("click", function(event) {
    clearTimeout(timeoutVar);
    if (!object.keepmealive) removeObject(object);
});

这种方法假定您的库函数会以某种方式负责删除或对object 执行任何需要执行的操作,因此一旦它开始运行,就不再需要删除函数。它将保留在原地,并准备好应对另一个可能的未来事件。

【讨论】:

    【解决方案3】:

    我会在处理过程中取消绑定事件,然后使用 s 递归函数重新绑定它,如下所示:

    var timeoutVar;
    var init = function(){
      $("#mydiv").on("mouseenter", function(event) {
        timeoutVar =  setTimeout(function() {
            $("#mydiv").off()
            runLibraryFunction(object, function(){
              init()
            });
        }, 5000);
      });
    };
    
    $("#mydiv").on("click", function(event) {
        clearTimeout(timeoutVar);
        removeObject(object);
    });
    
    init();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      相关资源
      最近更新 更多