Maa*_*ins 7 html javascript browser performance rendering
问题是关于以下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
One line of HTML code
<script>
// Synchronous delay of 5 seconds
var timeWhile = new Date().getTime();
while( new Date().getTime() - timeWhile < 5000 );
</script>
</body>
Run Code Online (Sandbox Code Playgroud)
我在Firefox和Chrome中对它进行了测试,它们在5秒后显示(渲染):"一行HTML代码",而不是在5秒内.为什么浏览器会这样做?
我理解为什么浏览器在执行JavaScript时必须停止渲染,因为你可以用JavaScript改变元素的样式(作为例子).如果浏览器必须在同一时刻完全显示和更改内容,则会出现问题.这就是浏览器在执行JavaScript时阻止渲染的原因.
在上面的示例中,当从执行JavaScript开始时,"HTML解析器"已经解析了"一行HTML代码".它必须,因为JavaScript可以包含例如document.write,所以附加的字符串必须在前面的HTML之后.显然,在"解析HTML"和显示/呈现相同的HTML之间有一段时间,因为否则此示例中的浏览器已经在5秒内显示了某些内容,但事实并非如此.
当您用大量HTML代码替换"一行HTML代码"时,浏览器将在5秒内显示一些内容,因此原则上可以显示一些内容.
如果我是一个浏览器,那么我会这样做:
在这样的示例中,浏览器可以在5秒前显示一些内容.这在渲染方面是一个很大的速度提升.
也许这是浏览器可以改进的东西,但也许还有其他原因.也许有人知道更多,并可以解释我.
解析和渲染是两个不同的操作,可以由浏览器独立运行,但两者都可以对 HTML/CSS/等代码的小片段进行操作,并且不需要完全加载所有资源来开始执行各自的工作。当然,渲染的任何内容都必须首先进行解析,但似乎解析不一定需要完全完成才能运行 JavaScript 代码,并且为了尽快开始向用户显示内容,这对于浏览器在解析完成之前开始渲染页面。
考虑对示例代码进行此修改(我在 macOS 上的 Google Chrome 版本 62.0.3202.75 中对此进行了测试):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
One line of html code
<script>
// Synchronous delay of 5 seconds
var timeWhile = new Date().getTime();
for (var current = new Date().getTime(); current - timeWhile < 5000; current = new Date().getTime()) {
if (current - timeWhile === 2500) {
alert(document.body.childNodes[0].nodeValue);
alert(document.body.childNodes[2].nodeValue);
}
};
</script>
Another line of HTML code
</body>Run Code Online (Sandbox Code Playgroud)
我alert()在代码中添加了 s 而不是console.log()s,因为刷新/写入 JavaScript 控制台似乎也被同步延迟阻止。
第一个alert()在页面上出现任何文本之前显示“一行 html 代码”字符串,证明页面的该部分在呈现之前已被解析。
然而,第二个alert()并没有发生。由于“另一行 HTML 代码”行尚未解析,因此它未定义为 的子节点document.body,因此尝试访问它会引发错误,导致警报无法显示,而是显示在 JavaScript 控制台中Uncaught TypeError: Cannot read property 'nodeValue' of undefined: 。
如果您在页面加载后在控制台中手动重新运行alert(document.body.childNodes[2].nodeValue);,您会如预期看到一条带有“另一行 HTML 代码”的警报。
我不确定为什么“一行 html 代码”字符串在同步延迟发生之前没有呈现在页面上,但我假设该行为特定于浏览器的实现。