clearTimeout 不适用于 mouseup 事件
clearTimeout not working on mouseup event
为什么在此设置中没有清除超时?我怎样才能使 up() 停止 运行 的延迟操作?
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 上清除延迟,但它仍在执行。
你总是在每一个动作上暂停。它不会取代最后一个...
你的代码基本上就是这样
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)
所以你需要在创建新的之前删除它
if (active) {
if (delay) window.clearTimeout(delay)
delay = setTimeout(function() {
console.log("move")
window.scrollTo(0,document.body.scrollHeight);
}, 50);
}
如果您需要多次触发,您需要查看节流脚本。
答案:
您的代码中有几处需要调整:
- 不要用新的
Timeout
计时器不断重新分配 delay
,只需使用 Interval
.
- 只有当状态处于活动状态时才应设置计时器 AND 延迟尚不存在。 这会停止现有的多个计时器
JavaScript中的定时器有几点需要调整和理解:
- 当您设置定时器时,容纳定时器的变量被设置为 return 一个整数。这是当前范围内定时器的 ID。
- 当您清除计时器时,变量不会重置为
undefined
- 它保持不变 Integer/ID。这是因为您没有清除 变量,范围正在停止与变量所在 ID 匹配的 Timer。
- 由于上述原因,您必须明确地将容纳计时器的变量设置为
undefined
(或其他一些 falsy
值)after 清除它存在检查工作。
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
仍被定义。我不认为你在技术上应该需要这个,但在实践中浏览器事件队列和定时器偶尔不会像预期的那样相处。
因此,我从回复中了解到,每次执行 move()
时,setTimeout
都会生成一个新的独立计时器。我的理解是每个新计时器都会覆盖前一个计时器,但由于情况并非如此,我不得不考虑其他事情。
我并没有真正解释我实际需要通过延迟实现什么,所以让我澄清一下。如果某个动作在 x 时间内没有执行,我想为该动作创建一个超时。在操作上使用 setTimeout 它自己会产生一个问题,即即使在 mouseup 事件之后,该操作仍可能有多个排队执行等待发生。
因此,我对一个新变量使用了 setTimeout,该变量充当操作的锁定。结果是下面的代码:
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
}
}
}
感谢大家的评论和回答。非常感谢。
为什么在此设置中没有清除超时?我怎样才能使 up() 停止 运行 的延迟操作?
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 上清除延迟,但它仍在执行。
你总是在每一个动作上暂停。它不会取代最后一个...
你的代码基本上就是这样
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)
所以你需要在创建新的之前删除它
if (active) {
if (delay) window.clearTimeout(delay)
delay = setTimeout(function() {
console.log("move")
window.scrollTo(0,document.body.scrollHeight);
}, 50);
}
如果您需要多次触发,您需要查看节流脚本。
答案:
您的代码中有几处需要调整:
- 不要用新的
Timeout
计时器不断重新分配delay
,只需使用Interval
. - 只有当状态处于活动状态时才应设置计时器 AND 延迟尚不存在。 这会停止现有的多个计时器
JavaScript中的定时器有几点需要调整和理解:
- 当您设置定时器时,容纳定时器的变量被设置为 return 一个整数。这是当前范围内定时器的 ID。
- 当您清除计时器时,变量不会重置为
undefined
- 它保持不变 Integer/ID。这是因为您没有清除 变量,范围正在停止与变量所在 ID 匹配的 Timer。 - 由于上述原因,您必须明确地将容纳计时器的变量设置为
undefined
(或其他一些falsy
值)after 清除它存在检查工作。
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
仍被定义。我不认为你在技术上应该需要这个,但在实践中浏览器事件队列和定时器偶尔不会像预期的那样相处。
因此,我从回复中了解到,每次执行 move()
时,setTimeout
都会生成一个新的独立计时器。我的理解是每个新计时器都会覆盖前一个计时器,但由于情况并非如此,我不得不考虑其他事情。
我并没有真正解释我实际需要通过延迟实现什么,所以让我澄清一下。如果某个动作在 x 时间内没有执行,我想为该动作创建一个超时。在操作上使用 setTimeout 它自己会产生一个问题,即即使在 mouseup 事件之后,该操作仍可能有多个排队执行等待发生。
因此,我对一个新变量使用了 setTimeout,该变量充当操作的锁定。结果是下面的代码:
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
}
}
}
感谢大家的评论和回答。非常感谢。