JavaScript setTimeout 0 阻塞页面渲染?
JavaScript setTimeout 0 blocking page rendering?
根据 Whosebug 问题
Changing the DOM is synchronous. Rendering the DOM actually happens after the JavaScript stack has cleared.
并且根据 this google 文档,屏幕刷新率 60fps 相当于大约每 16 毫秒刷新一次,我写了这个例子:
<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#do').onclick = function() {
document.querySelector('#status').innerHTML = 'calculating...';
// setTimeout(long, 0); // will block
setTimeout(long, 1); // will not block
};
function long(){
let result = 0
for (let i = 0; i < 1000; i++) {
for (let j = 0; j < 1000; j++) {
for (let k = 0; k < 1000; k++) {
result += i + j + k;
}
}
}
document.querySelector('#status').innerHTML = 'calculation done';
document.querySelector('#result').innerHTML = result.toString();
}
});
</script>
</head>
<body>
<button id='do'> Do long calc!</button>
<div id='status'></div>
<div id='result'></div>
</body>
</html>
使用 jsfiddle link
我仔细研究了代码,发现阻塞发生在 12 毫秒以下的时间延迟,并且发生更频繁,延迟更小。
我有两种不同的理解方式:
在这种情况下,只有 setTimeout
的时间延迟超过 16 毫秒不应阻塞,0 和 1 的时间延迟远小于 16 毫秒,因此它们都应该阻塞;
在 setTimeout
调用和 long
推送到消息队列之后(可选延迟),现在调用堆栈是空的,所以在这两种情况下 setTimeout
应该不阻塞并且 'calculating...' 总是被渲染。
我的理解有什么问题吗?
可能与你的browser throttling the delay有关。
它看起来好像大多数浏览器都忽略了值 0,可能值得为您的浏览器查看 DOM_MIN_TIMEOUT_VALUE
。
根据
Changing the DOM is synchronous. Rendering the DOM actually happens after the JavaScript stack has cleared.
并且根据 this google 文档,屏幕刷新率 60fps 相当于大约每 16 毫秒刷新一次,我写了这个例子:
<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#do').onclick = function() {
document.querySelector('#status').innerHTML = 'calculating...';
// setTimeout(long, 0); // will block
setTimeout(long, 1); // will not block
};
function long(){
let result = 0
for (let i = 0; i < 1000; i++) {
for (let j = 0; j < 1000; j++) {
for (let k = 0; k < 1000; k++) {
result += i + j + k;
}
}
}
document.querySelector('#status').innerHTML = 'calculation done';
document.querySelector('#result').innerHTML = result.toString();
}
});
</script>
</head>
<body>
<button id='do'> Do long calc!</button>
<div id='status'></div>
<div id='result'></div>
</body>
</html>
使用 jsfiddle link
我仔细研究了代码,发现阻塞发生在 12 毫秒以下的时间延迟,并且发生更频繁,延迟更小。
我有两种不同的理解方式:
在这种情况下,只有
setTimeout
的时间延迟超过 16 毫秒不应阻塞,0 和 1 的时间延迟远小于 16 毫秒,因此它们都应该阻塞;在
setTimeout
调用和long
推送到消息队列之后(可选延迟),现在调用堆栈是空的,所以在这两种情况下setTimeout
应该不阻塞并且 'calculating...' 总是被渲染。
我的理解有什么问题吗?
可能与你的browser throttling the delay有关。
它看起来好像大多数浏览器都忽略了值 0,可能值得为您的浏览器查看 DOM_MIN_TIMEOUT_VALUE
。