迹忆客 专注技术分享

当前位置:主页 > 学无止境 >

使用 setTimeout 加速 window.onload

作者:迹忆客 最近更新:2023/01/11 浏览次数:

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 事件不会在图像完全加载之前触发。

这给了我们一个稍微不同的结果:

  1. 浏览器的 HTML 解析器开始解析。
  2. 一旦 <img> 元素被解析,浏览器就会开始下载图像。
  3. 解析器一遇到开始的 <script> 标记就会停止。
  4. <script> 元素的内容被执行。 setTimeout 将导致一些其他代码在 3 秒内运行,并且事件处理程序绑定到 window.onload
  5. HTML 解析器继续解析文档直到结束。
  6. 一旦图像完全加载, onload 事件就会触发。
  7. 调用 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 毫秒。 我们可以在此处测试哪些浏览器遵循这方面的规范。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 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 的新手。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便