草庐IT

javascript - DOM执行顺序问题

coder 2024-07-26 原文

我在 HEAD 标签中有一些 JavaScript,它在页面上的最后一个脚本(当前已解析)之前动态插入异步加载脚本标签。这个动态包含的脚本标签包含需要在 DOM 可用之后解析 DOM 的 JavaScript,但在加载所有图像和脚本标签之前。重要的是,JavaScript 在所有 JS 加载之前开始执行,因为如果有一个挂起的脚本,这会导致糟糕的用户体验。这意味着我不能等待 DOMContentLoaded 事件触发。对于将动态包含脚本标记的第一段 JavaScript 放在哪里,我没有任何灵 active 。

我的问题是,不等待 DOMContentLoaded 事件而立即开始解析 DOM 对我来说是否安全?如果没有,我是否有办法在不等待 DOMContentLoaded 事件的情况下执行此操作?

最佳答案

...JavaScript in the HEAD ... dynamically inserts an asynchronously loading script tag before the last script on the page...

我假设 the loader script is inline ,这意味着突出显示的位实际上指的是“当前”脚本元素,即加载程序。发生这种情况是因为只有加载程序脚本标记之前的 html 已被解析和解释,因此插入的脚本标记实际上仍在 head 中,而不是在页面底部。因此,目标脚本仅限于对前面的元素执行 DOM 操作,除非您将代码包装到 DOM 就绪回调中……这是您首先要避免的!

基本上您想要加载所有 html 以便页面可见/可扫描,开始加载图像/样式表(发生在非阻塞线程中)然后然后加载任何 javascript。一种方法是 put your target script at the bottom of the page ,只需正确选择他们的顺序(首先是交互性,其次是增强功能,第三方分析/社交媒体集成/其他任何超重最后)并根据您的需求进行调整。技术上it still blocks the page load ,但页面底部只剩下脚本(由于它们位于底部,您可以在加载它们后立即直接操作 DOM,减去一些 IE7 怪癖)。

有一个相关的rant/overview我喜欢链接到它提供了不错的例子和一些关于使用和滥用 DOM 就绪回调的计时琐事,以及 "other side of the story"关于为什么出色的性能可能的值(value)低于理智的依赖管理框架。后者的主题过于宽泛,无法在一个答案中穷尽,但类似于 requirejs documentation。应该让您对模式的工作原理有一个清晰的认识。

也许要考虑的另一种模式是构建 SPA - 单页应用程序,它利用对内容 block 的异步访问,而不是在完整页面之间进行“传统”导航。该模式具有来自 not having to parse and re-execute shared javascript on every page 的低估但相当显着的性能优势,这也将解决您对第三方 js 性能的(有效)关注。毕竟,只是a good caching policy会为加载时间创造奇迹,但糟糕的 JavaScript 代码或大量框架的执行开销仍然存在。

更新:解决了这个问题。考虑到您的特定场景(即无法控制标记本身,并希望成为最后执行的脚本),您应该将 将异步脚本元素插入 DOM 包装到 0ms setTimeout 回调:

setTimeout(function(){

    //the rest is how GA operates
    var targetScript = document.createElement('script');
    targetScript.type = 'text/javascript';
    targetScript.async = true;
    targetScript.src = 'target.js';

    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(targetScript, s);

}, 0);

由于环境的单线程特性,js setTimeout 回调基本上被添加到一个队列中,以便在线程不再繁忙时立即执行 0ms 延迟 ( more thorough explanation here )。所以浏览器甚至不知道需要加载,更不用说执行目标脚本了,直到所有“更高优先级”的代码都完成!由于添加脚本标签时 DOM 是可操作的,因此您不必在目标脚本本身中显式检查它(这对于从缓存中“即时”加载时非常方便)。

关于javascript - DOM执行顺序问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21054118/

有关javascript - DOM执行顺序问题的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  3. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  4. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  5. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  6. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  7. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  8. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

随机推荐