异步和文档就绪
Posted
技术标签:
【中文标题】异步和文档就绪【英文标题】:Async and document ready 【发布时间】:2012-06-18 02:37:33 【问题描述】:我尝试通过在我的脚本中添加一些async
属性来优化我的页面。它似乎破坏了我的 javascript,因为 $(document).ready
在所有脚本加载之前执行!
我看到我可以通过输入$(window).load
而不是$(document).ready
来解决我的问题,但我想知道是否有更好的解决方案。
这个解决方案在我的案例中引发了 2 个问题:
-
我必须更改所有
$(document).ready
并告诉所有开发人员不要再使用它了
脚本将在所有图像加载后执行。我的网站有很多沉重的图片,我真的需要在 dom 准备好后尽快执行一些脚本。
你有一些魔术吗?也许将所有脚本放在最后?使用defer
而不是async
?
【问题讨论】:
在 jQuery 检测到文档就绪状态后,还会为使用 document.ready 的脚本执行文档就绪调用。在使用 jQuery 的网站上,在加载完所有资源后尝试使用以下内容:$(document).ready(function () console.log('READY'););
【参考方案1】:
经过一些广泛的研究,我可以肯定地说,将脚本放在页面末尾是最佳实践。
雅虎同意我的观点:http://developer.yahoo.com/performance/rules.html#js_bottom
Google 不谈论这种做法,似乎更喜欢异步脚本:https://developers.google.com/speed/docs/best-practices/rtt#PreferAsyncResources
恕我直言,将脚本放在页面末尾比异步/延迟有几个好处:
它适用于所有浏览器(是的,甚至 IE ;)) 您保证执行顺序 您不需要使用$(document).ready
或$(window).load
您的脚本可以在图像加载之前执行
作为异步/延迟,您的页面将显示得更快
当 DOM 触发 ready 事件时,所有脚本都被加载
可以通过将所有 js 合并到一个文件中来优化(通过 mod_pagespeed 之类的工具)
我能看到的唯一缺点是浏览器无法并行下载。 使用 async/defer 的一个很好的理由是当您有一个完全独立的脚本(不需要依赖执行顺序)并且不需要在特定时间执行时。示例:谷歌分析。
【讨论】:
它并不能通过将它们放在 DOM 中来完全保证执行。如果你的浏览器有太多的 JavaScript 和/或 HTML,你需要 requirejs 或任何其他类似的系统加载器。我看到了只适用于压缩 JavaScript 的设计,因为它太多了。这是一个引导 3.x 响应式主题,在向下滚动页面时会产生效果。 唯一一个在 2012 年不使用 defer 的有价值的论点是,正如 Yahoo 所说:Firefox 不支持 DEFER 属性。但是现在在 2020 年,您可以在任何地方使用延迟模式:caniuse.com/#feat=script-defer【参考方案2】:defer
在这里肯定会有所帮助。
defer
通常比async
好,因为它:
async
)
保证执行顺序(不同于async
)
在最后执行(不像async
在页面仍在加载时并行执行,它实际上停止 dom 解析!)
jquery ready
触发 在“延迟”脚本已加载(这就是您的要求)
This SO answer 有一张很好的图片说明了延迟/异步加载顺序,超级好理解。
【讨论】:
【参考方案3】:如果您不想使用脚本加载器,您可以使用以下方法,这样您就可以将 $(document).ready 脚本留在原处 - 修改如下:
$(()=>
function checkAllDownloads()
// Ensure your namespace exists.
window.mynamespace = window.mynamespace || ;
// Have each of your scripts setup a variable in your namespace when the download has completed.
// That way you can set async on all your scripts except jquery.
// Use the document ready event - this code - to check if all your scripts have downloaded.
if (window.mynamespace.script1 && window.mynamespace.script2)
// Proceed with page initialisation now that all scripts have been downloaded.
// [ Add your page initialisation code here ].
return;
// Not all downloads have completed.
// Schedule another check to give the async downloads time to complete.
setTimeout(checkAllDownloads, 500);
// check if it is safe to initialise the page by checking if all downloads have completed.
checkAllDownloads();
)
【讨论】:
以上是关于异步和文档就绪的主要内容,如果未能解决你的问题,请参考以下文章