首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >clearTimeout不处理mouseup事件

clearTimeout不处理mouseup事件
EN

Stack Overflow用户
提问于 2019-10-14 20:53:28
回答 3查看 659关注 0票数 0

为什么在此设置中超时未被清除?我如何弥补()阻止延迟动作的运行?

代码语言:javascript
运行
复制
var active = false;
var delay;

window.addEventListener("mousedown", down, false);
window.addEventListener("mouseup", up, false);
window.addEventListener("mousemove", move, false);

function down(e) {
    active = true;
    console.log("down")
    window.scrollTo(0,document.body.scrollHeight);
}

function up(e) {
    active = false;
    clearTimeout(delay); //expecting this to clear delay
    console.log("up")
    window.scrollTo(0,document.body.scrollHeight);
}

function move(e) {
    if (active) {
        delay = setTimeout(function() {
            console.log("move")
            window.scrollTo(0,document.body.scrollHeight);
        }, 50);
    }
}

期望在mouseup上清除延迟,但它仍然执行。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-10-20 00:49:53

因此,我从答复中了解到,每次执行setTimeout时,move()都会生成一个新的独立计时器。我的理解是,每一个新计时器都会覆盖前一个定时器,但由于情况并非如此,我不得不考虑其他的事情。

我并没有真正解释我到底需要做些什么来拖延时间,所以让我澄清一下。如果某个动作有x段时间没有执行,我想为该操作创建一个超时。通过对操作使用setTimeout,它自己创建了一个问题,即即使在mouseup事件之后,该操作仍然可能有多个排队的执行等待发生。

因此,我在一个新变量上使用了setTimeout,该变量充当操作的锁。结果是以下代码:

代码语言:javascript
运行
复制
var active = false;
var actionTimeout = false;
var actionTimeStamp;
var actionLock = false;

window.addEventListener("mousedown", down, false);
window.addEventListener("mouseup", up, false);
window.addEventListener("mousemove", move, false);

function down(e) {
    active = true;
    console.log("down")
    window.scrollTo(0,document.body.scrollHeight);
}

function up(e) {
    active = false;
    console.log("up")
    window.scrollTo(0,document.body.scrollHeight);
}

function move(e) {
    if (active) {
        if ((Date.now() - actionTimeStamp > 500) && (!actionTimeout)) { // get time elapsed and compare to threshold (500ms)
            actionTimeout = true; //this is for the if statement above to prevent multiple timeouts
            actionLock = false; // set the lock
            setTimeout(function() { // remove lock after 50ms
                actionTimeout = false;
                actionLock = true;
                actionTimeStamp = Date.now(); // timestamp here to make sure we don't lock again to soon. (helps if setTimeout is => than threshold.
            }, 50);
        }
        if (actionLock) { //do our action
            console.log("move")
            window.scrollTo(0,document.body.scrollHeight);
            actionTimeStamp = Date.now();  // timestamp last execution
        }
    }
}

感谢每一个人在评论和回答中插嘴。真的很感激。

票数 0
EN

Stack Overflow用户

发布于 2019-10-14 21:02:27

你每次动作都要暂停。它不能取代最后一个..。

您的代码基本上如下

代码语言:javascript
运行
复制
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- cancels this one
window.clearTimeout(delay)

所以你需要在创建一个新的

代码语言:javascript
运行
复制
if (active) {
    if (delay) window.clearTimeout(delay)
    delay = setTimeout(function() {
        console.log("move")
        window.scrollTo(0,document.body.scrollHeight);
    }, 50);
}

如果您需要移动到触发不止一次,您想查看节流脚本。

票数 1
EN

Stack Overflow用户

发布于 2019-10-14 21:12:27

答案:

在您的代码中有一些事情需要调整:

与使用新的Interval.

  • You计时器重新分配delay不同的是,
  • 只应在状态为active 延迟不存在的情况下设置定时器。这将阻止现有

中的多个定时器。

关于JavaScript中的计时器,有几件事需要调整和理解:

  • 设置计时器时,放置计时器的变量设置为返回整数。这是当前范围内计时器的ID。
  • 当您清除计时器时,变量不会重置为undefined --它保持不变的整数/ ID。这是因为您没有清除变量,作用域是停止与变量所在的ID匹配的计时器。由于上述原因,
  • 必须显式地将包含计时器的变量设置为undefined (或其他一些falsy值),然后清除该变量才能正常工作。

代码语言:javascript
运行
复制
var active = false;
var delay;

window.addEventListener("mousedown", down, false);
window.addEventListener("mouseup", up, false);
window.addEventListener("mousemove", move, false);

function down(e) {
    active = true;
    console.log("down")
    window.scrollTo(0,document.body.scrollHeight);
}

function up(e) {
    active = false;
    clearTimeout(delay); //expecting this to clear delay
    delay = undefined;
    console.log("up")
    window.scrollTo(0,document.body.scrollHeight);
}

function move(e) {
    if (active) {
      if(!delay) {
        delay = setInterval(function() {
            console.log("move")
            window.scrollTo(0,document.body.scrollHeight);
        }, 50);
      }
    }
  else { //fallback in case of Browser Queuing issues
   if(delay) { 
     clearTimeout(delay);
     delay = undefined;
   }
  }
}

编辑的

由于对问题的评论,我在mousemove中添加了一个回退,如果状态是非活动的,它将移除计时器,但是仍然定义了delay。我不认为您在技术上应该需要这样做,但实际上,浏览器事件队列和计时器有时并不像预期的那样进行。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58383928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档