动态加载Javascript及如何检查脚本是否存在

16

我正在使用以下技术动态加载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源文件已损坏,如何得到通知。

谢谢


关于onerror标签怎么样?https://dev59.com/2XRB5IYBdhLWcg3wuZQ1 - oak
在 script 标签中有一个 onerror 事件。当资源未找到时,它将触发。 - Hardik Solanki
10个回答

25

监听脚本元素的事件不是可靠的(来源)。一个可行的选择是使用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
@Lx1:是的,实际上您可以将setTimeout的超时时间缩短到10或20毫秒。如果我没记错的话,对于大多数浏览器来说,10毫秒是最小的超时时间。 - Daniel Vassallo
为什么您使用 !== 'undefined' 而不是(我认为通常的)!= 'undefined' - ashes999
!= 是比较值,!== 是比较引用。如果您使用 === 来比较值,它也会按预期工作。如果您使用 == 来比较包含相同值的引用,则是按值比较,否则是按引用比较。 - Gus Crawford
源代码 poo-pooing 事件监听脚本载入事件已过时(2007)...其中包含这个珠宝“在我测试的每个现代浏览器上都可以正常工作(IE 5.0和7.0;Firefox 2.0;Safari 1.3;Opera 7.54和9.10;Konqueror 3.5;iCab 3.0)... " - Brad Kent

3
动态加载脚本要简单得多:
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);    

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

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

第1步:创建回调函数:

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();
    }

Last: 把脚本像以前一样附加到网页的标签中。

document.body.appendChild(script);

如需更多信息,请参考此文章


3
很简单,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);

4
不太容易。如果该脚本已加载,它们将会触发该更新。我想知道如何检测脚本是否不存在。 - Lx1

1
你可以添加一个 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
}

希望这有所帮助。

0
在 onload 事件中,有状态码。200 表示良好,404 如您所知表示文件未找到。有帮助吗?

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

问题在于,你什么时候检查变量?<script>异步加载,并且将事件附加到<script>元素不可靠:http://unixpapa.com/js/dyna.html - Daniel Vassallo

0

抱歉打扰了,但这是我在这个确切情况下的第一个搜索结果,我相信我已经找到了更好的答案: 现在你可以从任何HTML元素中执行onloadevent回调来在加载到DOM后执行代码,你可以像这样使用它:

const script = document.createElement("script");
script.type = "text/javascript";
script.src = "file.js";
script.onload(() => {
    // ...whatever you want to excecute after loadinng the script
})
document.body.appendChild(script);

0
最近在我的vue.js项目中,我尝试做类似的事情,我正在使用es6所以请确保你拥有设置。这只是普通的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,它可能也有帮助。


-2
你使用哪个JavaScript库?
在jQuery中,如果通过Ajax加载脚本,你可以选择运行成功回调函数(和其他类型的回调)...
还有一个专门用于加载脚本的函数:$.getScript()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接