【问题标题】:Loading Javascript Dynamically and how to check if the script exists动态加载Javascript以及如何检查脚本是否存在
【发布时间】:2011-04-15 16:32:05
【问题描述】:

我正在使用以下技术来动态加载 Javascript:

var script = document.createElement("script");
script.type = "text/javascript";
script.src = "file.js";
document.body.appendChild(script);

这是一种很常见的方法。 这里也有讨论:http://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/

我知道如何在文件加载并执行后收到通知

我不知道的是,如果指向 Javascript 源文件的链接已损坏,我该如何收到通知。

谢谢

【问题讨论】:

标签: javascript


【解决方案1】:

一种方法是在您包含的脚本中定义一个变量,然后检查该变量是否已定义。

【讨论】:

  • 问题是……你什么时候检查变量? <script> 异步加载,将事件附加到 <script> 元素不可靠:unixpapa.com/js/dyna.html
【解决方案2】:

这很简单,Internet Explorer 会触发 onreadystatechange 事件,而其他浏览器会触发脚本对象的 onload 事件。

var newScript;
var loadFunc = function ()
{
    alert("External Javascript File has been loaded");
};
newScript = document.createElement('script');
newScript.setAttribute('type','text/javascript');
newScript.setAttribute('src','file.js');

//IE triggers this event when the file is loaded
if (elm.attachEvent)
{
    newScript.attachEvent('onreadystatechange',function() 
    {
        if (newScript.readyState == 'complete' || newScript.readyState == 'loaded')
            loadFunc();
    });
}

//Other browsers trigger this one
if (newScript.addEventListener)
    newScript.addEventListener('load', loadFunc, false);

document.getElementsByTagName('head')[0].appendChild(newScript);

【讨论】:

  • 这并不容易。如果脚本已加载,它们将触发该更新。我在问如何检测脚本是否不存在。
【解决方案3】:

侦听脚本元素上的事件被认为是不可靠的 (Source)。想到的一种选择是使用setTimeout() 来轮询您希望在外部脚本中定义的变量。在x 秒后,您可能会超时并认为脚本已损坏。

外部脚本:file.js:

var MyLibrary = { };

主文档:

var poll;
var timeout = 100; // 10 seconds timeout
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'file.js';
document.body.appendChild(script);

poll = function () {
  setTimeout(function () {
    timeout--;
    if (typeof MyLibrary !== 'undefined') {
      // External file loaded
    }
    else if (timeout > 0) {
      poll();
    }
    else {
      // External library failed to load
    }
  }, 100);
};

poll();

【讨论】:

  • 我希望有更好的。如果我处理速度较慢的服务器,我可以考虑在答案返回前一毫秒决定超时。
  • @Lx1:是的,您实际上可以将 setTimeout 的超时时间减少到 10 或 20 毫秒。如果我没记错的话,10 是大多数浏览器的最小超时时间。
  • 你为什么使用!== 'undefined'而不是(我认为是常态)!= 'undefined'
  • != 比较值,!== 比较引用。如果您使用 === 比较值,它也将按预期工作。如果您使用 == 比较包含相同值的引用,则您是按值比较,否则是引用。
  • 源 poo-pooing 事件侦听脚本加载事件已过时 (2007).. 包含这个 gem “这在我测试过的每个 modern_browser 上都可以正常工作(IE 5.0 和7.0;Firefox 2.0;Safari 1.3;Opera 7.54 和 9.10;Konqueror 3.5;iCab 3.0)..."
【解决方案4】:

你使用什么 JavaScript 库?

在 jQuery 中,如果您通过 Ajax 加载脚本,您可以选择运行成功回调函数(以及其他类型的回调)...

还有一个加载脚本的专用函数:$.getScript()

【讨论】:

    【解决方案5】:

    在 onload 事件中,有状态码。 200 很好,您可能还记得 404 表示未找到文件。有用吗?

    【讨论】:

      【解决方案6】:
      var script = document.createElement("script");
      script.type = "text/javascript";
      script.src = "file.js";
      

      您需要为此脚本添加回调。

      第一次:创建回调:

      function callbackFn(callbackArgs) = {
             console.log("script is loaded with the arguments below");
             console.log(callbackArgs);
          }
      

      第二次:向脚本添加事件监听器。 Firefox 和 Chrome 都支持 onload 事件,因此您可以像这样使用它:

      script.onload = callbackFn();
      

      对于 IE... 您可以为状态更改添加事件侦听器,如下所示:

      script.onreadystatechange = function() {
          if ( this.readyState != "loaded" ) return;
          callbackFn();
          }
      

      最后:像以前一样将脚本附加到正文中。

      document.body.appendChild(script);
      

      更多信息,请参考this acticle

      【讨论】:

        【解决方案7】:

        动态加载脚本要简单得多:

        var script = document.createElement('script');
        script.onload = function () {
          main_function();  // Main function to call or anything else or nothing  
        };
        script.src = "yourscript.js";
        document.head.appendChild(script);    
        

        【讨论】:

          【解决方案8】:

          您可以附加一个onload 属性,在该属性中,您可以调用将在JS 文件加载后执行的函数。

          检查代码:

          var jsElement = document.createElement("script");
          jsElement.type = "application/javascript";
          jsElement.src = "http://code.jquery.com/jquery-latest.min.js";
          jsElement.setAttribute("onload","getMeAll()");
          document.body.appendChild(jsElement);
          function getMeAll(){
              //your code goes here
          }
          

          希望这会有所帮助。

          【讨论】:

            【解决方案9】:

            最近在我的 vue.js 项目中,我尝试过这样的事情,我使用的是 es6,所以请确保你有设置。这只是 vanilla javascript,所以它应该可以毫无问题地运行。

            function handleLoad() {
              // on scirpt loaded logic goes here
              ...
            };
            
            function handleLoadError(yourScript) {
              // on scirpt loading error logic goes here
              ...
            
              // remove the script element from DOM if it has some error
              document.head.removeChild(yourScript);
            };
            
            function generatePan(token) {
              // if script does not exist only then append script to DOM
              if (!document.getElementById('your-script')) {
                const yourScript = document.createElement('script');
                yourScript.setAttribute('src', 'https://your-script.js');
                yourScript.setAttribute('id', 'your-script');
                yourScript.async = true;
                yourScript.addEventListener('load', () => handleLoad(), false);
                yourScript.addEventListener('error', () => handleLoadError(yourScript), false);
            
                document.head.appendChild(yourScript);
              } else {
                // runs if script is already loaded DOM
                handleLoad();
              }
            };
            

            另外,请检查此 link,即使这可能会有所帮助。

            【讨论】:

              猜你喜欢
              • 2013-11-22
              • 1970-01-01
              • 1970-01-01
              • 2012-03-28
              • 2018-11-13
              • 1970-01-01
              • 1970-01-01
              • 2015-04-16
              • 2023-01-15
              相关资源
              最近更新 更多