异步(async)是否比延迟(defer)更好?

8
我理解的方式是,脚本应该使用defer而不是async,因为这样解析就不需要停止执行它们(我参考了这些图表)。如果解析必须停止,那么页面内容显示起来就需要更长时间,对吗?如果是这样的话,为什么async会比defer更好呢?
例如:我在我的网站上使用Google reCAPTCHA。Google要求我在我的结束</head>标签之前插入脚本。
    <script src='https://www.google.com/recaptcha/api.js'></script>
</head>

为什么这个脚本需要在页面加载完成之前执行?我不应该使用defer吗?

然而,使用defer需要更长的时间才能执行脚本,那么为什么这样做会更好呢?最终,正如您在图表中所看到的,它需要相同的组合时间。 - Bergi
@Bergi 但是在执行 async 脚本时,页面渲染不会停止吗? - bumbleshoot
渲染从未停止,我猜你的意思是解析。即使如此(实际上并不必要),这有什么优势呢?为什么不早些执行脚本会更好呢? - Bergi
@Bergi 或许我有误解?我认为在解析过程中,页面元素正在加载并显示在用户屏幕上。如果解析在任何时候停止,则页面元素需要更长时间才能显示出来。我现在意识到,也许我们实际上直到所有解析和JavaScript执行完成后才能看到内容。这正确吗? - bumbleshoot
@Bergi 那么什么情况下会使用 async 而不是 defer 呢?对我来说,似乎在解析/渲染完成之前执行脚本可能会稍微延迟渲染。 - bumbleshoot
显示剩余3条评论
2个回答

11

好的,在搜索互联网数小时后,我终于得到了答案!来自这篇精彩的博客文章

使用ASYNC加载的脚本在资源下载完成后立即解析和执行。而DEFER脚本直到HTML文档解析完成(也就是DOM Interactive或performance.timing.domInteractive)才会执行。

...

比较ASYNC和DEFER的瀑布流,我们可以看到使用DEFER会使DOM Interactive更早地触发,并且允许渲染更快地进行。
然而:
即使ASYNC和DEFER不会阻塞HTML解析器,它们仍然可能会阻塞渲染。当它们在渲染完成之前被解析和执行,并占据浏览器主线程时,就会发生这种情况。规范中没有任何内容表明它们必须等待渲染完成。
基本上,我从中了解到的是渲染(虽然 它与解析有些并行)使用 defer 更快,但由于在整个渲染过程中执行所有 JavaScript 脚本,最终页面加载时间仍然需要一样长。这对用户来说稍微更加令人满意,因为他们可以更早地看到东西出现。然而,如果我们真的想要提高加载速度,我们应该在可能的情况下 在 onload 后加载脚本总之:似乎没有理由使用 async 而不是 defer

9
这个答案是错误的。没有硬性规定。如果你有一个很大的js文件,它的下载速度比DomInteractive还慢,在这种情况下使用defer会导致浏览器在解析和发出DomContentLoaded之前等待该脚本被下载。如果你还有其他的脚本正在等待这个事件(比如jQuery),它们将不必要地等待你推迟的脚本下载完成。使用async可以避免这种情况。 - calumbrodie
@calumbrodie,如果您能够撰写自己的答案回复我的原始问题,我会非常感激,因为我真的想要理解这是如何工作的!我很难理解您的解释,可能是因为我不知道所有的术语,因为我已经很久没有再次审查这些概念了。许多人都在查看这个问题,所以正确的答案将非常有帮助。 - bumbleshoot
我的理解与calumbrodie的类似,尽管它还不像我想的那样清晰。我认为普遍的误解可能与这个事实有关:没有一种适用于所有情况的方法(总能让你最快地到达FOO),而且每个人都使用小文件和执行时间作为例子来演示美丽的图表。 - Jan Kyu Peblik
1
如果脚本被缓存,它就不需要下载,但在 DomContentLoaded 被触发之前仍然需要执行。我想最好的解决方案是:如果您使用 defer,请确保所有脚本都依赖于 defer,而不是 DomContentLoaded。如果您无法做到这一点(例如,您依赖于您无法控制的第三方脚本),那么 async 更好。 - OdraEncoded

0

是的,异步有时比延迟更优,有时则不如。这可以通过计时直到您关心的事件发生来测试使用异步或延迟(或加载、由加载插入等)的时间。许多浏览器甚至配备了内置的开发人员工具,以显示定时事件的“瀑布”。

您提到的图表在概念上很漂亮且有用,但它们根本没有提供科学度量。只有测量您关心的事件的时间才能始终(统计上)准确地告诉您哪个最快。

您要么测试一个东西,要么仅仅依赖信仰。

(就谷歌reCAPTCHA而言,我不太了解它,但我知道在某些实现中,它会尝试通过各种可用标准(例如,甚至是在与CAPTCHA交互之前鼠标光标的移动方式)预先确定页面是否可能被实际的人类使用。人类在页面完全加载之前经常与页面进行交互,因此这段时间将在这方面提供有用的信息。话虽如此,如果脚本对您有效,无论您的实现方式如何,即使在某些方面劣于另一种实现方式,它也可以正常工作。如果您没有确定成功功能的方法,那么您将永远迷失方向。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接