草庐IT

javascript - 一旦第三方脚本加载失败,立即运行一段 JavaScript

coder 2023-08-09 原文

我为几个网站提供了一个 JavaScript 小部件,它们是异步加载的。我的小部件反过来需要加载另一方提供的脚本,这在我的控制范围之外。

有几种方法可以检查该脚本是否已成功加载。但是,如果该脚本加载失败,我还需要运行不同的代码。

明显不起作用的工具包括:

  • 我不愿意使用 JavaScript 库,例如 jQuery。我需要一个非常小的脚本来最大程度地减少对使用我的小部件的网站的影响。

  • 我想尽快检测到故障,所以使用计时器轮询它是不可取的。不过,我不介意在旧浏览器上使用计时器作为最后的手段。

  • 我找到了 <script>标签的 onerror事件在某些主要浏览器中不可靠。 (这似乎取决于安装了哪些附加组件。)

  • 任何涉及 document.write 的事情马上就出来了。 (除了该方法本质上是邪恶的之外,我的代码是异步加载的,因此 document.write 可能会对页面造成不良影响。)

我之前有一个解决方案涉及加载 <script>在一个新的<iframe> .在那个 iframe 中,我设置了一个 <body onload=...>检查是否为 <script onload=...> 的事件处理程序事件已经触发。因为<script>是初始文档的一部分,后来没有异步注入(inject),onload仅在网络层完成 <script> 后触发标签。

但是,现在我需要在父文档中加载脚本;它不能再出现在 iframe 中。因此,我需要一种不同的方式来在网络层放弃尝试获取脚本时立即触发代码。

我读了“Deep dive into the murky waters of script loading”,试图找出我可以跨浏览器依赖的排序保证。

如果我理解那里记录的技术:

  • 我需要将故障处理代码放在一个单独的 .js 中文件。
  • 然后,在某些浏览器上,我可以确保我的代码仅在第三方脚本运行或失败后运行。这要求浏览器支持:
    • 设置<script async>通过 DOM 属性为 false,
    • 或使用 <script onreadystatechange=...>在 IE 6+ 上。

尽管看着 async support table , 我不知道我是否可以在足够多的浏览器中依赖脚本排序来实现这一点。

那么,在我无法控制的脚本加载过程中,我该如何可靠地处理失败呢?

最佳答案

我相信我已经解决了我提出的问题,但事实证明这并没有解决我实际遇到的问题。那好吧。这是我的解决方案:

我们想在浏览器完成加载第三方脚本后运行一些代码,这样我们就可以检查它是否加载成功。我们通过限制仅在第三方脚本运行或失败后才加载回退脚本来实现这一点。然后,回退脚本可以检查第三方脚本是否创建了它应该创建的全局变量。

http://www.html5rocks.com/en/tutorials/speed/script-loading/ 启发的跨浏览器顺序脚本加载.

var fallbackLoader = doc.createElement(script),
    thirdPartyLoader = doc.createElement(script),
    thirdPartySrc = '<URL to third party script>',
    firstScript = doc.getElementsByTagName(script)[0];

// Doesn't matter when we fetch the fallback script, as long as
// it doesn't run early, so just set src once.
fallbackLoader.src = '<URL to fallback script>';

// IE starts fetching the fallback script here.

if('async' in firstScript) {
    // Browser support for script.async:
    // http://caniuse.com/#search=async
    //
    // By declaring both script tags non-async, we assert
    // that they need to run in the order that they're added
    // to the DOM.
    fallbackLoader.async = thirdPartyLoader.async = false;
    thirdPartyLoader.src = thirdPartySrc;
    doc.head.appendChild(thirdPartyLoader);
    doc.head.appendChild(fallbackLoader);
} else if(firstScript.readyState) {
    // Use readyState for IE 6-9. (IE 10+ supports async.)
    // This lets us fetch both scripts but refrain from
    // running them until we know that the fetch attempt has
    // finished for the first one.
    thirdPartyLoader.onreadystatechange = function() {
        if(thirdPartyLoader.readyState == 'loaded') {
            thirdPartyLoader.onreadystatechange = null;
            // The script-loading tutorial comments:
            // "can't just appendChild, old IE bug
            // if element isn't closed"
            firstScript.parentNode.insertBefore(thirdPartyLoader, firstScript);
            firstScript.parentNode.insertBefore(fallbackLoader, firstScript);
        }
    };
    // Don't set src until we've attached the
    // readystatechange handler, or we could miss the event.
    thirdPartyLoader.src = thirdPartySrc;
} else {
    // If the browser doesn't support async or readyState, we
    // just won't worry about the case where script loading
    // fails. This is <14% of browsers worldwide according to
    // caniuse.com, and hopefully script loading will succeed
    // often enough for them that this isn't a problem.
    //
    // If that isn't good enough, you might try setting an
    // onerror listener in this case. That still may not work,
    // but might get another small percentage of old browsers.
    // See
    // http://blog.lexspoon.org/2009/12/detecting-download-failures-with-script.html
    thirdPartyLoader.src = thirdPartySrc;
    firstScript.parentNode.insertBefore(thirdPartyLoader, firstScript);
}

关于javascript - 一旦第三方脚本加载失败,立即运行一段 JavaScript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20207336/

有关javascript - 一旦第三方脚本加载失败,立即运行一段 JavaScript的更多相关文章

  1. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  4. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  5. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  6. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  7. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  8. ruby - 使用 rbenv 和 ruby​​-build 构建 ruby​​ 失败,出现 undefined symbol : SSLv2_method - 2

    我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby​​2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby​​-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm

  9. Ruby 在 n *milli* 秒后超时一段代码 - 2

    在Ruby中,我需要在n毫秒秒后暂停一段代码的执行。我知道RubyTimeout库支持秒的超时:http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/index.html这可能吗? 最佳答案 只需为超时使用十进制值。n毫秒的示例:Timeout::timeout(n/1000.0){sleep(100)} 关于Ruby在n*milli*秒后超时一段代码,我们在StackOverflow上找到一个类似的问题: https:

  10. ruby-on-rails - Ruby 的 'open_uri' 是否在读取或失败后可靠地关闭套接字? - 2

    一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我

随机推荐