【问题标题】:How to detect if javascript files are loaded?如何检测是否加载了javascript文件?
【发布时间】:2010-11-20 13:43:00
【问题描述】:

加载 JavaScript 文件时是否会触发事件?问题出现是因为 YSlow 建议将 JavaScript 文件移动到页面底部。这意味着 $(document).ready(function1) 在包含 function1 代码的 js 文件加载之前触发。

如何避免这种情况?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    我没有方便的参考,但是脚本标签是按顺序处理的,所以如果你把你的$(document).ready(function1)放在定义function1等的脚本标签之后的脚本标签中,你应该很好去。

    <script type='text/javascript' src='...'></script>
    <script type='text/javascript' src='...'></script>
    <script type='text/javascript'>
    $(document).ready(function1);
    </script>
    

    当然,另一种方法是通过在构建过程中组合文件来确保您总共只使用一个脚本标签。 (除非您从某个地方的 CDN 加载其他的。)这也将有助于提高您页面的感知速度。

    编辑:刚刚意识到我实际上并没有回答你的问题:我认为没有触发跨浏览器事件,不。 如果你足够努力的话,见下文。您可以测试符号并使用 setTimeout 重新安排:

    <script type='text/javascript'>
    function fireWhenReady() {
        if (typeof function1 != 'undefined') {
            function1();
        }
        else {
            setTimeout(fireWhenReady, 100);
        }
    }
    $(document).ready(fireWhenReady);
    </script>
    

    ...但如果您的脚本标签顺序正确,则不必这样做。


    更新:如果您愿意,您可以获得动态添加到页面的script 元素的加载通知。要获得广泛的浏览器支持,您必须做两件不同的事情,但作为一种组合技术,这是可行的:

    function loadScript(path, callback) {
    
        var done = false;
        var scr = document.createElement('script');
    
        scr.onload = handleLoad;
        scr.onreadystatechange = handleReadyStateChange;
        scr.onerror = handleError;
        scr.src = path;
        document.body.appendChild(scr);
    
        function handleLoad() {
            if (!done) {
                done = true;
                callback(path, "ok");
            }
        }
    
        function handleReadyStateChange() {
            var state;
    
            if (!done) {
                state = scr.readyState;
                if (state === "complete") {
                    handleLoad();
                }
            }
        }
        function handleError() {
            if (!done) {
                done = true;
                callback(path, "error");
            }
        }
    }
    

    根据我的经验,错误通知 (onerror) 并非 100% 跨浏览器可靠。另请注意,某些浏览器会同时执行这两种机制,因此使用 done 变量来避免重复通知。

    【讨论】:

    • 感谢您的回答,但对我来说,为什么要在
    • 之后?我没有关注你。
    • 这很好,但如果你使用 jQuery,也可以考虑$.getScript() api.jquery.com/jQuery.getScript
    • 对于动态加载器,您忘记了 appendChild。不过还是很棒的代码。
    • @Steverino: 不,除非您使用 async 或 defer 属性来改变事情,否则 HTML 中的 script 标记会使页面加载停止,直到该脚本代码运行(因为它可能会输出带有document.write 的东西),所以您肯定知道较早的script 在以后的script 之前已加载(或失败)。 (浏览器很乐意并行下载脚本,但它们确保它们按照 HTML 中的顺序执行。)async 和 defer 改变了这一点。见:html.spec.whatwg.org/multipage/scripting.html#attr-script-async
    【解决方案2】:

    当他们说“页面底部”时,他们并不是字面上的意思:他们的意思是在结束 &lt;/body&gt; 标记之前。将您的脚本放在那里,它们将在 DOMReady 事件之前加载;之后放置它们,DOM 将在加载之前准备好(因为在解析结束 &lt;/html&gt; 标记时它就完成了),正如您发现的那样,这将不起作用。

    如果您想知道我是如何知道他们的意思的:我曾在 Yahoo!我们把我们的脚本放在&lt;/body&gt;标签之前:-)

    编辑:另见 T.J. Crowder 的回复,并确保您的物品顺序正确。

    【讨论】:

      【解决方案3】:

      看看 jQuery 的 .load() http://api.jquery.com/load-event/

      $('script').load(function () { }); 
      

      【讨论】:

      • :) 有时有用的功能
      【解决方案4】:

      进一步@T.J. Crowder 的回答,我添加了一个递归外循环,它允许遍历数组中的所有脚本,然后在加载所有脚本后执行一个函数:

      loadList([array of scripts], 0, function(){// do your post-scriptload stuff})
      
      function loadList(list, i, callback)
      {
          {
              loadScript(list[i], function()
              {
                  if(i < list.length-1)
                  {
                      loadList(list, i+1, callback);  
                  }
                  else
                  {
                      callback();
                  }
              })
          }
      }
      

      当然,如果你愿意,你可以制作一个包装器来去掉“0”:

      function prettyLoadList(list, callback)
      {
          loadList(list, 0, callback);
      }
      

      干得好@T.J. Crowder - 我对在其他线程中看到的“在运行回调之前添加几秒钟的延迟”感到畏缩。

      【讨论】:

        【解决方案5】:

        我总是从 JavaScript 文件的末尾调用来注册它的加载,它曾经对所有浏览器都非常适合我。

        例如:我有一个 index.htm、Js1.js 和 Js2.js。我在 index.htm 头文件中添加函数 IAmReady(Id) 并使用文件末尾的参数 1 和 2 调用它,分别是 Js1 和 Js2。一旦从两个 js 文件中获得两次调用(将调用次数存储在静态/全局变量中),IAmReady 函数将具有运行启动代码的逻辑。

        【讨论】:

          【解决方案6】:

          更改脚本的加载顺序,以便在 ready 回调中使用之前定义 function1。

          另外,我总是发现将 ready 回调定义为匿名方法然后命名为更好。

          【讨论】:

          • 因为它在 javascript 文件中,所以之前无法定义它。
          • 您可以先包含具有function1 定义的文件,然后包含另一个使用该函数的文件。关键是你不能只是随机添加脚本文件。
          【解决方案7】:

          像 T.J. wrote:顺序是定义的(至少当你的浏览器要执行任何JavaScript时它是连续的,即使它可能以某种方式并行下载脚本)。但是,显然您遇到了麻烦,也许您正在使用产生一些 404 Not Found 或超时的第三方 JavaScript 库?如果是,请阅读Best way to use Google’s hosted jQuery, but fall back to my hosted library on Google fail.

          【讨论】:

            猜你喜欢
            • 2011-05-01
            • 1970-01-01
            • 2012-08-29
            • 1970-01-01
            • 1970-01-01
            • 2011-09-20
            • 1970-01-01
            • 2014-07-09
            • 1970-01-01
            相关资源
            最近更新 更多