HTML <script defer> 可以在 <script async> 之前执行吗?
Can HTML <script defer> execute before <script async>?
我要问的是一个已经深入探讨过的问题,而且我的问题有很多接近的答案,但我没能找到一个简单问题的确切答案.
我知道延迟脚本 运行 按照它们在页面上出现的顺序,但只有在构建 DOM 之后,我会尽快得到异步脚本 运行尽可能,我知道没有人阻止 HTML 解析器。
这里的问题是:是否存在延迟脚本可以在所有异步脚本执行之前执行的情况?本质上,如果 HTML 解析器已经解析了整个文档并准备好 运行 延迟脚本但是仍然有一些异步脚本尚未加载,它是否会等待这些异步脚本加载(并执行),还是 运行 延迟脚本?
谢谢!
从一个非常简单的测试来看,似乎 defer
不会等待 async
脚本加载...但是(总有一个但是)它似乎也取决于浏览器。
我 运行 在 Chrome 41、Firefox 36 和 Internet Explorer 11 上进行了测试,Chrome 和 FF 得到了相同的结果(defer
在 async
) 但在 IE 上的结果不同(async
总是在 defer
之前执行)。
如果 IE 忽略 async
属性(立即解析并执行代码),这可以解释,但根据 W3Schools and MDN,IE10 支持 async
。所以我想,IE 以不同于其他浏览器的方式处理异步调用,使其加载并执行 faster/before 整个页面被解析(然后 运行ning 在延迟脚本之前)。
这是我用于测试的 HTML 代码:
<!doctype html>
<html>
<head>
<title>Test</title>
<script type="text/javascript" src="./async.js"></script>
<script type="text/javascript" src="./defer.js"></script>
</head>
<body>
Testing
</body>
</html>
现在async.js的内容:
console.log("async");
以及defer.js的内容:
console.log("defer");
如果我运行它"as is",控制台结果是:
async
defer
这是意料之中的,因为脚本是在浏览器继续解析页面之前立即执行的。
现在我们来玩一下 async
和 defer
,看看结果:
代码:
<script type="text/javascript" src="./defer.js" defer></script>
<script type="text/javascript" src="./async.js" async></script>
结果:
defer
async
[注意:这是 Chrome 和 Firefox 上的结果;对于 IE,控制台是异步的然后延迟]
Defer.js 在 async.js 之前执行。不过可能是因为 async.js 放在代码的后面,所以让我们交换它们。
代码:
<script type="text/javascript" src="./async.js" async></script>
<script type="text/javascript" src="./defer.js" defer></script>
结果:
defer
async
[注意:这是 Chrome 和 Firefox 上的结果;对于 IE,控制台是异步的然后延迟]
Defer.js 仍然在 async.js 之前执行,即使之前调用过 async.js。所以回答你的问题:是的,在某些情况下,延迟脚本会在所有异步脚本加载和解析之前执行。
代码:
<script type="text/javascript" src="./async.js"></script>
<script type="text/javascript" src="./defer.js" defer></script>
或
<script type="text/javascript" src="./defer.js" defer></script>
<script type="text/javascript" src="./async.js"></script>
结果:
async
defer
这个结果是预期的,因为在这种情况下 async.js 被立即执行,并且 defer 等待页面解析(即使我们交换 script
位置也会得到相同的结果) .
最后测试一个在没有 async/defer 之前调用的异步脚本(不需要反过来测试,因为它会在调用异步之前立即执行):
代码:
<script type="text/javascript" src="./async.js" async></script>
<script type="text/javascript" src="./defer.js"></script>
结果:
defer
async
是的,理论上可以在具有 defer
脚本的脚本之后执行具有 async
属性的脚本。您应该相应地编写脚本。
即使在实践中不会发生这种情况,您仍然应该以这种期望编写脚本,因为规范不保证 async
脚本将在 defer
脚本之后执行,因此浏览器可以自由地以这种方式执行。
我要问的是一个已经深入探讨过的问题,而且我的问题有很多接近的答案,但我没能找到一个简单问题的确切答案.
我知道延迟脚本 运行 按照它们在页面上出现的顺序,但只有在构建 DOM 之后,我会尽快得到异步脚本 运行尽可能,我知道没有人阻止 HTML 解析器。
这里的问题是:是否存在延迟脚本可以在所有异步脚本执行之前执行的情况?本质上,如果 HTML 解析器已经解析了整个文档并准备好 运行 延迟脚本但是仍然有一些异步脚本尚未加载,它是否会等待这些异步脚本加载(并执行),还是 运行 延迟脚本?
谢谢!
从一个非常简单的测试来看,似乎 defer
不会等待 async
脚本加载...但是(总有一个但是)它似乎也取决于浏览器。
我 运行 在 Chrome 41、Firefox 36 和 Internet Explorer 11 上进行了测试,Chrome 和 FF 得到了相同的结果(defer
在 async
) 但在 IE 上的结果不同(async
总是在 defer
之前执行)。
如果 IE 忽略 async
属性(立即解析并执行代码),这可以解释,但根据 W3Schools and MDN,IE10 支持 async
。所以我想,IE 以不同于其他浏览器的方式处理异步调用,使其加载并执行 faster/before 整个页面被解析(然后 运行ning 在延迟脚本之前)。
这是我用于测试的 HTML 代码:
<!doctype html>
<html>
<head>
<title>Test</title>
<script type="text/javascript" src="./async.js"></script>
<script type="text/javascript" src="./defer.js"></script>
</head>
<body>
Testing
</body>
</html>
现在async.js的内容:
console.log("async");
以及defer.js的内容:
console.log("defer");
如果我运行它"as is",控制台结果是:
async
defer
这是意料之中的,因为脚本是在浏览器继续解析页面之前立即执行的。
现在我们来玩一下 async
和 defer
,看看结果:
代码:
<script type="text/javascript" src="./defer.js" defer></script>
<script type="text/javascript" src="./async.js" async></script>
结果:
defer
async
[注意:这是 Chrome 和 Firefox 上的结果;对于 IE,控制台是异步的然后延迟]
Defer.js 在 async.js 之前执行。不过可能是因为 async.js 放在代码的后面,所以让我们交换它们。
代码:
<script type="text/javascript" src="./async.js" async></script>
<script type="text/javascript" src="./defer.js" defer></script>
结果:
defer
async
[注意:这是 Chrome 和 Firefox 上的结果;对于 IE,控制台是异步的然后延迟]
Defer.js 仍然在 async.js 之前执行,即使之前调用过 async.js。所以回答你的问题:是的,在某些情况下,延迟脚本会在所有异步脚本加载和解析之前执行。
代码:
<script type="text/javascript" src="./async.js"></script>
<script type="text/javascript" src="./defer.js" defer></script>
或
<script type="text/javascript" src="./defer.js" defer></script>
<script type="text/javascript" src="./async.js"></script>
结果:
async
defer
这个结果是预期的,因为在这种情况下 async.js 被立即执行,并且 defer 等待页面解析(即使我们交换 script
位置也会得到相同的结果) .
最后测试一个在没有 async/defer 之前调用的异步脚本(不需要反过来测试,因为它会在调用异步之前立即执行):
代码:
<script type="text/javascript" src="./async.js" async></script>
<script type="text/javascript" src="./defer.js"></script>
结果:
defer
async
是的,理论上可以在具有 defer
脚本的脚本之后执行具有 async
属性的脚本。您应该相应地编写脚本。
即使在实践中不会发生这种情况,您仍然应该以这种期望编写脚本,因为规范不保证 async
脚本将在 defer
脚本之后执行,因此浏览器可以自由地以这种方式执行。