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 毫秒以下的时间延迟,并且发生更频繁,延迟更小。

我有两种不同的理解方式:

  1. 在这种情况下,只有 setTimeout 的时间延迟超过 16 毫秒不应阻塞,0 和 1 的时间延迟远小于 16 毫秒,因此它们都应该阻塞;

  2. setTimeout 调用和 long 推送到消息队列之后(可选延迟),现在调用堆栈是空的,所以在这两种情况下 setTimeout 应该不阻塞并且 'calculating...' 总是被渲染。

我的理解有什么问题吗?

可能与你的browser throttling the delay有关。

它看起来好像大多数浏览器都忽略了值 0,可能值得为您的浏览器查看 DOM_MIN_TIMEOUT_VALUE