Javascript DOMContentLoaded阻止页面加载

Javascript DOMContentLoaded阻止页面加载,javascript,dom,Javascript,Dom,请参见代码: <!-- ... --> <head> <style type="text/css"> body { background: gray; } </style> </head> <body> <p> Firefox does not even shows blank page. Tab is stuck in "suggested sites" for

请参见代码:

<!-- ... -->
<head>
    <style type="text/css"> body { background: gray; } </style>
</head>
<body>
    <p>
        Firefox does not even shows blank page.
        Tab is stuck in "suggested sites" for 5 seconds.
    </p>
    <p>
        Chrome show just blank white. No text, no background. For 5 seconds.
    </p>
    <p>
        DOMContentLoaded event handler blocks page
        loading and rendering. Browser does not start
        rendering page until DOMContentLoaded
        handler function return.
    </p>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            var timestamp = Date.now() + 5000; while (Date.now() < timestamp);
            // or synchronous 5 seconds XHR as an equivalent of loop
        });
    </script>
</body>
<!-- ... -->

正文{背景:灰色;}

Firefox甚至不显示空白页面。
标签卡在“建议站点”中5秒钟。

铬显示为空白白色。没有文字,没有背景。5秒钟。

DOMContentLoaded事件处理程序块页面 加载和渲染。浏览器无法启动 在加载DOMContentLoaded之前呈现页面 处理函数返回。

document.addEventListener('DOMContentLoaded',function(){ var timestamp=Date.now()+5000;而(Date.now()
静态html+css足以呈现内容(虽然没有IMG,但良好布局的块不依赖于IMG大小)。一般的页面布局应该立即显示,就像它一直打算。 只有在渲染(或者至少开始绘制)之后,JavasCript才应该运行,不管它是控制单击绑定还是循环,如这里的示例所示

静态页面布局实际呈现后,或者至少开始显示后,如何运行JS?

(且“准备就绪”事件不适用于此处,因为无法保证在任何合理时间内开火)

  • 正如您从示例中看到的,我既不使用文档编写,也不打算使用
  • 我还将脚本放在正文结束标记的前面
  • 我没有在脚本标签中做任何实际工作-我订阅了事件
为什么浏览器阻止(阻止)用户查看静态定义的内容?至少现代浏览器能阻止这种胡说八道吗

UPD澄清


如果将DOMContentLoaded用于看似无害的常规任务(订阅按钮事件、初始化其他代码的异步加载等),实际上会延迟用户查看内容,这就是DOMContentLoaded的真正问题。在这个例子中,循环阻塞是故意的,只是为了证明它确实阻塞了,对于那些错误地认为DOMContentLoaded是“异步”/“非阻塞”安全的东西的人来说(事实并非如此)。

有趣且出乎意料。我用requestAnimationFrame(回调)解决了这个问题,如下所示:

function foo() {
    window.requestAnimationFrame(function() {
        window.requestAnimationFrame(function() {
            var timestamp = Date.now() + 5000; while (Date.now() < timestamp){};
            alert('now');
        });
    });
}
document.addEventListener('DOMContentLoaded', foo);
函数foo(){
window.requestAnimationFrame(函数(){
window.requestAnimationFrame(函数(){
var timestamp=Date.now()+5000;而(Date.now()
非常好的发现,谢谢。这正是我所期望的。奇怪的是,对于这些基本的事情,没有其他方便和标准的方法,问题被忽略了。好吧,这很烦人。Chrome喜欢第二个动画帧,但不喜欢第一个。更新答案。。。。我害怕在IE中尝试这个;)如果您实际上不需要与动画帧同步,请不要使用rAF。使用setTimeout满足一般超时需求。现在还不太清楚你想在这里实现什么。@AndréDion是的,还不完全清楚,但我认为阻塞是故意的——他只是想在显示主要内容后启动。while()可能是同步ajax调用的存根……André,“load”不是选项,它在“dependent resources”之后启动(页面图像、iFrame等)可以下载,在某些情况下需要数十秒甚至更长时间。