您可以在 HTML 标记上同时使用 async 和 defer 属性吗?

问题描述 投票:0回答:6

我想使用

defer
async
加载以下 JavaScript 代码:

<script defer async src="/js/somescript.js"></script>

由于 Internet Explorer 5.5+ 支持

defer
,正如您在 CanIUse.com 中看到的那样,如果异步不可用,我想优雅地回退到使用 defer。我认为异步可用时最好使用它,但直到 Internet Explorer 10 才支持它。

我的问题是上面的代码是有效的 HTML 吗?如果没有,是否可以使用 JavaScript 创建这种情况,当

defer
不可用时,优雅地回退到在脚本上使用
async

javascript html asynchronous
6个回答
151
投票

来自规范:https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async

即使指定了 async 属性,也可以指定 defer 属性,从而导致仅支持 defer(而不是异步)的旧版 Web 浏览器回退到 defer 行为,而不是默认的同步阻塞行为。

(查看下面的参考链接,查看普通脚本与延迟和异步脚本之间差异的直观表示)


参考资料:


26
投票

不幸的是,当指定

defer
时,
async
会被忽略,并且
async
始终具有更高的优先级。

我个人认为

defer
被现代浏览器(支持
async
)忽略是非常糟糕的。让我们想象一下当我们希望尽快初始化一些 JS 的情况,甚至在加载页面内容之前。但我们希望该脚本在需要它的其余脚本之前初始化。它应该位于
defer
队列中的第一个。但不幸的是,这行不通:

<!-- we want "jQuery" ASAP and still in "defer" queue. But defer is ignored by modern browsers. -->
<script src="jquery.min.js" async defer></script>

<!-- this doesn't blocks the content and can wait the full page load, but requires "jQuery" -->
<script src="some_jquery_plugin.min.js" defer></script>

在此示例中,“some_jquery_plugin.min.js”可以在加载 jQuery 之前加载并执行,但会失败。 :(

因此有两种方法可以解决这个问题:要么只使用

defer
指令,要么将所有依赖的 javascript 文件合并到单个 JS 中以安全地使用
async


23
投票

问题是,您希望它做什么? 如果 asyncdefer 都存在,我希望脚本被推迟,并且仅在浏览器空闲时在 DOMContentLoaded 之后执行,但如果我正确阅读规范,如果 async ,则看起来 defer 被忽略 已设置并且脚本是异步加载的,因此将在可用时立即执行,这很可能在 DOMContentLoaded 之前执行,并且可能会阻止其他资源。

使用这些属性可以选择三种可能的模式。如果存在 async 属性,则脚本将在可用时立即异步执行。如果 async 属性不存在,但存在 defer 属性,则当页面完成解析时执行脚本。如果这两个属性都不存在,则在用户代理继续解析页面之前立即获取并执行脚本。

https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async


12
投票

不。 您需要使用

defer
async
,但不能同时使用两者。有关更多信息,请参阅比较并根据您的需要使用。

defer属性:首先会下载脚本文件,然后等待html解析。 html解析结束后,脚本将被执行。换句话说,它将保证所有脚本在 html 解析后都会执行。

当脚本用于 DOM 操作时,Defer 属性非常有用。意味着脚本将应用于文档 html。

async 属性: 它将下载脚本文件并执行,无需等待 html 解析结束。换句话说,它不能保证所有脚本在 html 解析后都会执行。

当脚本不用于 DOM 操作时,异步属性非常有用。有时,您只需要脚本来进行服务器端操作或处理缓存或 cookie,而不需要 DOM 操作。意味着脚本与使用的 html 无关。


11
投票

是的,它是有效的 HTML,并且会按预期工作。

任何符合 W3C 标准的浏览器都将识别 async 属性并正确处理脚本,而旧版 IE 版本将识别 defer 属性。

由于这两个属性都是 boolean,因此您不必必须分配任何值。


1
投票

实际上,这里的大多数评论都存在误解。人们似乎不知道DEFER也可以并行加载代码,就像ASYNC一样。但它会在 DOM 加载后(但在 DOMContentLoaded 执行之前)等待执行,而 ASYNC 在加载后、DOM 加载之前立即运行它。由于 ASYNC 和 DEFER 都是并行加载代码的,因此无需同时使用两者(但也许是为了处理遗留问题)。

© www.soinside.com 2019 - 2024. All rights reserved.