10

有一个类似的问题没有解决。

我遇到了这样一种情况,即侦听 DOMContentLoaded 的处理程序可以阻止第一次绘制。有时会阻塞,有时不会

我尝试了很多次 cmd + R 来查看它。这种行为有什么解释吗?

我还录制了一段视频来展示这一点: https ://www.youtube.com/watch?v=EDZQ1nLCK2w&feature=youtu.be

  1. 当您在重新加载后看到一个空白页面时,这意味着 DOMContentLoaded 阻止了第一次绘制
  2. 当您看到文本“一些文本”然后重新加载后出现空白页时,这意味着 DOMContentLoaded 没有阻止第一次绘制
window.addEventListener('DOMContentLoaded', () => {
    let i = 0;
    while (i++ < 1000000000) {
        continue;
    }
    document.getElementById('el').remove();
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <p id="el">Some text</p>
</body>
</html>
4

2 回答 2

2

这是一个竞赛条件。有时,在您添加侦听器之前,文档已经加载/交互。

您可以通过检查文档的 readyState:document.readyState来查看差异。您的代码没有运行,因为有时状态已经是interactiveor complete,这意味着DOMContentLoaded在您实际添加侦听器之前事件已经触发。

处理它的方法是这样的:

function init() {
    let i = 0;
    while (i++ < 1000000000) {
        continue;
    }
    document.getElementById('el').remove();
}

if (document.readyState === 'loading') {
    // Document not yet loaded, so wait for it.
    window.addEventListener('DOMContentLoaded', init);
} else {
    // Document is ready (interactive or complete), so call init immediately.
    init();
}
于 2020-07-28T12:37:20.217 回答
0

我想到了。Blink渲染引擎中存在同步调度 DOMContentLoaded 事件的错误

// #blink/renderer/core/dom/document.cc
// #blink::Document::FinishedParsing

// FIXME: DOMContentLoaded is dispatched synchronously, but this should be
// dispatched in a queued task, see https://crbug.com/425790
if (document_timing_.DomContentLoadedEventStart().is_null())
  document_timing_.MarkDomContentLoadedEventStart();
DispatchEvent(*Event::CreateBubble(event_type_names::kDOMContentLoaded));
if (document_timing_.DomContentLoadedEventEnd().is_null())
  document_timing_.MarkDomContentLoadedEventEnd();
SetParsingState(kFinishedParsing);

** 为什么它有时被异步发送我不知道。现在,就我而言,它始终是同步的(在提出问题时可能还有一个错误)

于 2022-01-23T12:28:16.203 回答