在 Firefox 上的 DOMContentLoaded 之前运行的异步回调

Async callback running before DOMContentLoaded on Firefox

本文关键字:运行 异步 回调 Firefox 上的 DOMContentLoaded      更新时间:2023-09-26

我一直在做一些实验来理解DOMContentLoaded事件。在实验过程中,我发现了Firefox和Chrome(在Ubuntu上)之间的有趣差异。

我有这个 HTML 文件:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script>
        console.log('script is running');
        document.addEventListener( "DOMContentLoaded", function() {
            console.log('DOM content loaded');
        }, false );
        var x = 0;
        for(var i = 0; i < 900000000; i++) {
            x++;
        }
        setTimeout(function() {
            console.log('timeout callback is running');
        }, 10);
        console.log('script finished');
    </script>
</head>
<body>
    <div>div content</div>
</body>
</html>

火狐控制台中的输出:

script is running
script finished
timeout callback is running
DOM content loaded

在Chrome控制台中,我得到:

script is running
script finished
DOM content loaded
timeout callback is running

如果我将超时提高到 100 毫秒,我也会在 Firefox 中获得 Chrome 的输出。

那么,似乎在 Firefox 上,超时回调"劫持"了下一帧,即使触发了DOMContentLoaded?或者也许它仅在回调返回后触发?

[编辑]

我添加了一个动态加载的脚本:

console.log('script is running');
document.addEventListener( "DOMContentLoaded", function() {
    console.log('DOM content loaded');
}, false );
setTimeout(function() {
    console.log('timeout callback is running');
}, 1);
var script = document.createElement('script');
script.src = 'dynamic.js';
document.head.appendChild(script);
var x = 0;
for(var i = 0; i < 1000000000; i++) {
    x++;
}
console.log('script finished');

动态.js:

(function() {
    console.log('dynamic script is running');
    var x = 0;
    for(var i = 0; i < 2000000000; i++) {
        x++;
    }
    console.log('dynamic script finished');
})();

现在,火狐控制台输出是:

script is running
file:///foo/bar/dynamic.js
script finished
dynamic script is running
dynamic script finished
timeout callback is running
DOM content loaded

所以 Firefox 甚至在 DOMContentLoaded 回调运行之前等待动态加载的脚本返回?

两者都是异步的,它们没有因果关系。这是一个预期的竞争条件 - 有时 DOM 快于 10 毫秒,有时则不然。

当然,结果 - 如果它们是可重现的 - 可能表明Chrome比Firefox更快,或者Firefox只是优先考虑超时而不是DOM事件。这不重要。没有一个实现是"错误的"。