我正在查看一个网络应用程序中的一些现有代码,我看到了这个:
window.setTimeout(function () { ... })
window.setTimeout(function () { ... })
setTimeout不一定会立即运行,即使将延迟明确设置为0也是如此。原因是setTimeout将函数从执行队列中移除,并且它只会在JavaScript完成当前执行队列后才被调用。
console.log(1);
setTimeout(function() {console.log(2)});
console.log(3);
console.log(4);
console.log(5);
//console logs 1,3,4,5,2
了解更多详情,请参见http://javascriptweblog.wordpress.com/2010/06/28/understanding-javascript-timers/
setTimeout
函数有一个最短延迟时间(HTML5规定为4毫秒,Firefox 3.6为10毫秒)。有关此问题的讨论详见Mozilla开发者中心的文档页面。
delay
的描述如下:delay
或使用0
将在下一个事件循环中执行,但可能需要更长的时间。这是它与直接执行函数内容不同的第一个原因。例如:
document.getElementById("runNow").addEventListener("click", runNow);
document.getElementById("runNoDelay").addEventListener("click", runNoDelay);
function runNow() {
clearLog();
addLog("Start");
addLog("Hello");
addLog("End");
}
function runNoDelay() {
clearLog();
addLog("Start");
setTimeout(function() {
addLog("Hello");
});
addLog("End");
}
function clearLog() {
const log = document.getElementById("log");
while (log.lastElementChild) {
log.removeChild(log.lastElementChild);
}
}
function addLog(message) {
const newLine = document.createElement("pre");
newLine.textContent = message;
document.getElementById("log").appendChild(newLine);
}
<button id="runNow">Run Now</button>
<button id="runNoDelay">Run With No Delay</button>
<div id="log"></div>
setTimeout
时,“End”消息会在“Hello”之前出现。0
,也有可能需要更长时间,原因可能包括:
document.getElementById("run").addEventListener("click", run);
function run() {
clearLog();
const now = new Date().getMilliseconds();
setTimeout(function() {
timeout(0, now);
});
}
function clearLog() {
const log = document.getElementById("log");
while (log.lastElementChild) {
log.removeChild(log.lastElementChild);
}
}
function timeout(nestingLevel, last) {
const now = new Date().getMilliseconds();
logline(nestingLevel, now, last);
if (nestingLevel < 9) {
setTimeout(function() {
timeout(nestingLevel + 1, now);
});
}
}
function logline(nestingLevel, now, last) {
const newLine = document.createElement("pre");
newLine.textContent = `${nestingLevel} ${now - last}`;
document.getElementById("log").appendChild(newLine);
}
<button id="run">Run</button>
<pre>nesting level delay</pre>
<div id="log"></div>
(改编自 MDN 上的示例)。
请注意,直到嵌套级别达到一定点时,延迟时间为 0
(或接近 0
)。
还要注意,setTimeout
使用包装函数(function () { ... }
)调用,这意味着如果立即执行函数内容,this
的值将与包装函数相同。
Chrome(版本 92.0.4515.131)和 Firefox(版本 91.0)在嵌套级别为 4 时强制最小超时为 4 毫秒,如上面的示例所示。
HTML 标准 表示:“如果嵌套级别大于 5,并且超时小于 4,则将超时设置为 4”。
我的理解是,这些浏览器将此最小超时强制应用于第 7 个任务的调度,其中嵌套级别为 6(大于 5)。
归根结底,如果浏览器希望使用其他实现定义的时间长度,那么这是一个有趣但无关紧要的问题。
你缺少了毫秒参数...
setTimeout(function() { /*something*/ }, 0);
0 将延迟设置为 0,但实际上它的作用是让您的函数"跳过队列"浏览器执行列表。 浏览器有很多事情要做,例如呈现页面上的对象,通过调用此函数,您的函数将在浏览器有一些周期时立即运行。