为什么 DOMContentLoaded 处理程序可以阻止第一次绘制?
Why DOMContentLoaded handler can block first paint?
有一个没有解决。
我遇到过侦听 DOMContentLoaded 的处理程序可以阻止首次绘制的情况。
有时会阻塞,有时不会
我试了很多次cmd+R都看到了。对这种行为有什么解释吗?
我还录制了一个视频来展示这个:
https://www.youtube.com/watch?v=EDZQ1nLCK2w&feature=youtu.be
- 当您在重新加载后看到空白页面时,这意味着 DOMContentLoaded 阻止了第一次绘制
- 当您看到文本“Some text”,然后在重新加载后出现空白页时,这意味着 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>
这是一个竞争条件。有时在添加侦听器之前文档已经 loaded/interactive。
您可以通过检查文档的就绪状态来了解差异:document.readyState。您的代码不是 运行,因为有时状态已经是 interactive
或 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();
}
我明白了。 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);
** 为什么有时会异步发送我不知道。现在,在我这边,它总是同步的(可能在提出问题时还有一个错误)
有一个
我遇到过侦听 DOMContentLoaded 的处理程序可以阻止首次绘制的情况。 有时会阻塞,有时不会
我试了很多次cmd+R都看到了。对这种行为有什么解释吗?
我还录制了一个视频来展示这个: https://www.youtube.com/watch?v=EDZQ1nLCK2w&feature=youtu.be
- 当您在重新加载后看到空白页面时,这意味着 DOMContentLoaded 阻止了第一次绘制
- 当您看到文本“Some text”,然后在重新加载后出现空白页时,这意味着 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>
这是一个竞争条件。有时在添加侦听器之前文档已经 loaded/interactive。
您可以通过检查文档的就绪状态来了解差异:document.readyState。您的代码不是 运行,因为有时状态已经是 interactive
或 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();
}
我明白了。 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);
** 为什么有时会异步发送我不知道。现在,在我这边,它总是同步的(可能在提出问题时还有一个错误)