【问题标题】:Can clearTimeout clear the timeout even after the timeout maturity has been reached but not gotten the chance of execution yet?即使在已经达到超时成熟度但还没有获得执行机会的情况下,clearTimeout 是否可以清除超时?
【发布时间】:2014-06-12 20:03:51
【问题描述】:
假设我有一个运行客户端的函数 render,可能需要 100-1000 毫秒
我有一个函数 fetch 发出服务器请求,成功后清除渲染超时,然后以 100 毫秒的超时调用渲染。
我有一个按钮,onclick 再次清除渲染超时,然后以 100 毫秒的超时调用渲染。
我发现当我尝试多次单击该按钮时,并且如果发出了许多服务器请求,则只有第一个和最后一个响应会按预期导致呈现。
但这能保证吗?我可以放心地依赖它吗?
任何让我放心或告诉我有关陷阱的链接将不胜感激。
我经历过this
我知道无论如何,如果发生任何 asyc 事件,它将仅在第一次执行空闲时排队并执行,但我对关于队列中应该包含什么的 决定 感到困惑因为那是由浏览器完成的?
【问题讨论】:
标签:
javascript
jquery
callback
onclick
settimeout
【解决方案1】:
我找不到好的来源,所以我尝试在浏览器中运行这个脚本。
var doItLater = function () {
alert("I did it!");
};
window.onload = function () {
// set a timeout to execute immediately
var timeout = window.setTimeout(doItLater, 0);
for (var i = 0; i < 1000000000; i++) {
// waste some time
}
// The timeout has definitely triggered by now.
// doItLater is queued up to execute as soon as
// this function returns.
clearTimeout(timeout); // wait, I changed my mind!
};
// Does doItLater get called?
而且它有效! clearTimeout() 阻止 doItLater() 被调用,即使它已经被放置在队列中。
附带说明一下,我绝对建议在您的渲染函数中使用 setTimeout() within 来防止页面变得无响应。 1000 毫秒对于阻塞事件循环的函数来说太长了。 (例如,见here)
【解决方案2】:
我认为这是特定于 JS 运行时实现的。例如,this SO 问题表明,在 IE 上,即使在调用了clearTimeout() 之后,也有可能执行超时回调。
鉴于 JS 事件链的单线程特性,我建议您在调用 clearTimeout() 之前或之后设置一个控制标志,并在超时回调中检查该标志:
var isActive = true;
var timerId = setTimeout(function() {
if (!isActive) return;
// doStuff
}, someInterval);
...
function onSomeExternalEvent() {
isActive = false;
clearTimeout(timerId);
}