使用 setTimeout 加速 window.onload
setTimeout()
中的 JavaScript 代码不一定会延迟 onload
事件。 考虑以下测试用例:
<!DOCTYPE html>
<meta charset="utf-8">
<title>setTimeout() and window.onload</title>
<script>
setTimeout(function() {
document.body.style.background = 'red';
}, 3000);
window.onload = function() {
document.body.style.background = 'green';
};
</script>
打开此文档时会发生以下情况:
-
浏览器的 HTML 解析器会执行它的操作,但一旦遇到开始的
<script>
标记就会停止。 -
<script>
元素的内容被执行。setTimeout
将导致一些其他代码在 3 秒内运行,并且事件处理程序绑定到window.onload
。 - HTML 解析器继续解析文档直到结束。
-
由于此页面上没有其他资源,因此一旦解析器完成,就会触发
onload
事件。 -
调用
window.onload
事件处理程序。 该文档获得绿色背景。 -
大约 3 秒后,
setTimeout
函数启动。文档变成红色背景。
在此示例中,使用 setTimeout
不会延迟 onload
事件。 注意,其他场景不一定如此! 例如,考虑以下文档:
<!DOCTYPE html>
<meta charset="utf-8">
<title>setTimeout() and window.onload</title>
<img src="image.png">
<script>
setTimeout(function() {
document.body.style.background = 'red';
}, 3000);
window.onload = function() {
document.body.style.background = 'green';
};
</script>
如各位所见,我们已将图像添加到文档中。 (当然,这可能是阻止 onload
的任何其他资源。)onload
事件不会在图像完全加载之前触发。
这给了我们一个稍微不同的结果:
- 浏览器的 HTML 解析器开始解析。
-
一旦
<img>
元素被解析,浏览器就会开始下载图像。 -
解析器一遇到开始的
<script>
标记就会停止。 -
<script>
元素的内容被执行。setTimeout
将导致一些其他代码在 3 秒内运行,并且事件处理程序绑定到window.onload
。 - HTML 解析器继续解析文档直到结束。
-
一旦图像完全加载,
onload
事件就会触发。 -
调用
window.onload
事件处理程序。 该文档获得绿色背景。
如大家所见,此列表中缺少一个步骤,仅仅是因为无法准确预测它应该去哪里。 setTimeout
中的代码将在步骤 4 后 3 秒执行,我们知道很多。 但是取决于下载图像需要多长时间,这可能是在加载之前或之后。
假设图片加载需要 1 秒。 这意味着 onload
事件也会在大约一秒钟后触发。 两秒后,setTimeout
中的代码将最终执行。
如果图像加载需要 5 秒,onload
事件将在此期间再次延迟,因此 setTimeout
中的代码将在 onload
之前执行。
如果加载图像需要大约 3 秒,即 setTimeout
的延迟参数,会发生什么情况? onload
会在 setTimeout
中的代码之前、期间或之后触发吗?
要回答这个问题,我们需要了解 JavaScript 是单线程的。(关于这一点,可以参考我们的 setTimeout究竟做了什么 这篇文章) 如果在浏览器准备好触发 onload
时有一些代码正在运行(来自内联脚本或来自 setTimeout
内部),则浏览器将必须“等待”直到脚本完成才能处理 onload
。 同样,如果我们使用 setTimeout
下载资源,并且它们在 onload
触发之前进入下载队列,那么加载这些资源将(仍然)延迟 onload
。
换句话说,使用 setTimeout
并不能保证在所有情况下都能加速 onload
事件。 但大多数时候,它会。
这有用吗?
这意味着我们可以使用 setTimeout(fn, 0)
模式来防止延迟 onload
事件,从而导致感知加载/渲染时间减少。 当然,这种技术只能用于非依赖的脚本。
我认为跟踪脚本就是一个很好的例子。 其中大多数动态地将新的 <script>
元素插入到 DOM 中。 如各位所知,每个 DOM 操作都会带来一定的性能损失。 例如,默认的 Google Analytics 代码会在遇到代码段时立即修改 DOM,从而延迟 onload
事件。
这是 Google Analytics 片段的修改版本,使用 setTimeout
来防止延迟加载:
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
setTimeout(function() {
var g = document.createElement('script'),
s = document.scripts[0];
g.src = 'https://ssl.google-analytics.com/ga.js';
s.parentNode.insertBefore(g, s);
}, 0);
一些注意事项
如前所述,此技术不能用于依赖的脚本。 很难预测 setTimeout(fn, 0)
中的 fn 何时会执行。 如果你有两个或三个这样的结构,就无法判断它们的执行顺序。
另请注意
,setTimeout
中函数的this
绑定会自动覆盖到全局窗口对象。 这可能会破坏依赖于this
引用的脚本。
请注意
,HTML5 规范允许的最小setTimeout
超时值为 4 毫秒。 较小的值(如 0)应限制在 4 毫秒。 我们可以在此处测试哪些浏览器遵循这方面的规范。
相关文章
检查 Windows 上是否安装了 MongoDB
发布时间:2023/04/20 浏览次数:66 分类:MongoDB
-
本文介绍了四种不同的方法,可帮助您检查 Windows 上是否安装了 MongoDB 软件。
在 Windows 中备份 MySQL 数据库
发布时间:2023/04/19 浏览次数:75 分类:MySQL
-
本快速教程将讨论备份 MySQL 数据库并将其作为脚本保存在文件中。使用数据库时,建议定期备份数据库。
如何在 Windows 系统中卸载 git
发布时间:2023/04/09 浏览次数:212 分类:Git
-
在这篇简短的文章中,我们将学习如何卸载 Git,以及如何在从个人计算机的目录中卸载 Git 后删除这些文件。
在 Windows 上将 Git 添加到 PATH
发布时间:2023/04/07 浏览次数:183 分类:Git
-
Git 是一个免费的开源版本控制系统,旨在快速高效地处理项目。你可以在 Windows、Mac 和 Linux 操作系统上使用它。本文介绍了将 git 程序添加到 Windows 路径环境变量。
在 Windows 上更新 Git
发布时间:2023/04/07 浏览次数:202 分类:Git
-
Git 是一个免费的开源版本控制系统,旨在快速高效地处理项目。在 Windows、Mac 和 Linux 操作系统上使用此工具。本文介绍如何将 Windows 上的 Git 更新到最新版本。
在 Windows 上关闭 Git 提交编辑器
发布时间:2023/03/30 浏览次数:68 分类:Git
-
在本文中,我们将讨论如何退出 Git 提交编辑器。 这可能有点棘手,尤其是如果您是 Git bash 的新手。
在 PHP 变量中存储 Div Id 并将其传递给 JavaScript
发布时间:2023/03/29 浏览次数:69 分类:PHP
-
本文教导将 div id 存储在 PHP 变量中并将其传递给 JavaScript 代码。