当前位置:首页>WordPress教程>JavaScript的defer与async属性应用详解

JavaScript的defer与async属性应用详解

大量的网页中会引入脚本,它通常比的体积更大,更重一些,所以处理时间也更长。当加载 HTML 时遇到,浏览器就不能继续构建 DOM,必须等待JavaScript脚本执行完毕。对于外部脚本也是一样的:浏览器必须等脚本下载完,并执行结束,才能继续处理剩余的页面。

因此会导致两个重要的问题:

  1. 脚本不能访问到位于它们下面的 DOM 元素,脚本无法给它们添加处理程序等。
  2. 如果页面顶部有一个笨重的脚本,它会“阻塞页面”。在该脚本下载并执行结束前,用户不能看到页面内容。

通常的做法是将JavaScript脚本放置到网页的尾部,这样,它可以访问到它上面的元素,并且不会阻塞页面显示内容。但是这种解决方案远非完美。例如,浏览器只有在下载了完整的 HTML 文档之后才会注意到该脚本(并且可以开始下载它)。对于长的 HTML 文档来说,这样可能会造成明显的延迟。

这对于使用高速连接的人来说,这不值一提,他们不会感受到这种延迟。但是这个世界上仍然有很多地区的人们所使用的速度很慢,特别是一些地区的移动网络。

幸运的是,这里有deferasync 两个特性可以为解决这个问题。

defer特性

defer特性告诉浏览器不要等待脚本,浏览器将继续处理 HTML,构建 DOM。JavaScript脚本会“在后台”下载,然后等 DOM 构建完成后,脚本才会执行。

<!doctype html>
<body>
<p>...content before script...</p>

<script defer src="https://zhanzhangb.com/test.js"></script>

<!-- 以下内容立即可见 -->
<p>...defer应用实例...</p>
</body>

换句话说:

  • 具有defer特性的脚本不会阻塞页面。
  • 具有defer特性的脚本总是要等到 DOM 解析完毕,但在DOMContentLoaded事件之前执行。

以下示例将解释第二句话的意思:

<p>...content before scripts...</p>

<script>
  document.addEventListener('DOMContentLoaded', () => alert("DOM ready after defer!"));
</script>

<script defer src="https://zhanzhangb.com/test.js"></script>

<p>...脚本后的内容会立即显示...</p>
  1. 页面内容立即显示。
  2. DOMContentLoaded事件处理程序等待具有defer特性的脚本执行完成。它仅在脚本下载且执行结束后才会被触发。

具有defer特性的脚本保持其相对顺序,就像常规脚本一样。

假设,我们有两个具有defer特性的脚本:test1.js在前,test2.js在后。

<script defer src="https://zhanzhangb.com/test1.js"></script>
<script defer src="https://zhanzhangb.com/test2.js"></script>

浏览器扫描页面寻找脚本,然后它们,以提高性能。因此,在上面的示例中,两个脚本是并行下载的。test2.js可能会先下载完成。

但是,defer特性除了告诉浏览器“不要阻塞页面”之外,还可以确保脚本执行的相对顺序。即使test2.js先加载完成,它也需要等到test1.js执行结束才会被执行。

当我们需要先加载 JavaScript 库,然后再加载依赖于它的脚本时,这可能会很有用。

注意:defer特性仅适用于外部脚本。如果脚本没有src,则会忽略defer特性,对于内联脚本是无效的。

async特性

async特性与defer有些类似。它也能够让脚本不阻塞页面。但是,在行为上二者有着重要的区别。

async特性意味着脚本是完全独立的:

  • 浏览器不会因async脚本而阻塞(与defer类似)。
  • 其他脚本不会等待async脚本加载完成,同样,async脚本也不会等待其他脚本。
  • DOMContentLoaded和异步脚本不会彼此等待:
    • DOMContentLoaded可能会发生在异步脚本之前(如果异步脚本在页面完成后才加载完成)
    • DOMContentLoaded也可能发生在异步脚本之后(如果异步脚本很短,或者是从 中加载的)

换句话说,async脚本会在后台加载,并在加载就绪时运行。DOM 和其他脚本不会等待它们,它们也不会等待其它的东西。async脚本就是一个会在加载完成时执行的完全独立的脚本。

async不会按照脚本顺序执行,谁先加载完成,就先执行它。

当我们将独立的第三方脚本集成到页面时,此时采用方式是非常棒的:计数器,等,因为它们不依赖于我们的脚本,我们的脚本也不应该等待它们:

<!-- Google Analytics 脚本通常是这样嵌入页面的 -->
<script async src="https://google-analytics.com/analytics.js"></script>

总结

asyncdefer有一个共同点:加载这样的脚本都不会阻塞页面的渲染。因此,用户可以立即阅读并了解页面内容。

但是,它们之间也存在一些本质的区别:

顺序 DOMContentLoaded
async 加载优先顺序。脚本在文档中的顺序不重要 —— 先加载完成的先执行 不相关。可能在文档加载完成前加载并执行完毕。如果脚本很小或者来自于缓存,同时文档足够长,就会发生这种情况。
defer 文档顺序(它们在文档中的顺序) 在文档加载和解析完成之后(如果需要,则会等待),即在DOMContentLoaded之前执行。

在实际开发中,defer用于需要整个 DOM 的脚本,和/或脚本的相对执行顺序很重要的时候。

async用于独立脚本,例如计数器或广告,这些脚本的相对执行顺序无关紧要。

原文地址:https://www.zhanzhangb.com/1951.html

WordPress教程

将WordPress 5.7默认的jQuery 3.5.1升级到jQuery 3.6.0

2024-1-24 3:16:58

WordPress教程

避免字体加载过程中出现不可见的文本

2024-1-24 3:17:03

个人中心
今日签到
有新私信 私信列表
搜索