2011-08-04 46 views
10

我试图在脚本完全加载后执行某些操作。 (IE8)动态创建脚本:readyState永远不会“完成”

脚本我用来测试:http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js
和无效之一:http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.minaaaaaaaa.js

代码...

var script = create the element and append to head... 

// this works fine with FF/Chrome/... 
script.onload = function() {alert('script loading complete');} 
script.onerror = function() {alert('error loading script');} 

// and for IE 
script.onreadystatechange = function() { 
    // this will alert 1.loading 2.loaded 
    alert(this.readyState); 

    // this never works 
    if(this.readyState == 'complete') {alert('script loading complete');} 

    // this works with either a valid or INVALID url 
    else if(this.readyState == 'loaded') {alert('script loaded');} 
}; 

在我的情况下, “完整” 永不显示,即使网址无效,“已加载”也会显示。因此无法判断脚本是否正确加载到UNDER IE中。

我做错了什么?我怎么从来没有得到完整的状态?

UPDATE

OK,我只是看了一些文章,似乎readyState为不检测脚本加载的可靠方法。

那么还有其他的方法吗?没有jQuery,但纯Javascript。

+0

我不确定你想要做什么,但我建议寻找'jQuery#getScript'来获得如何动态加载脚本的想法。最重要的是,使用AJAX模式可以让您测试HTTP错误,因为您似乎想到了这一点。这不能 - afaik - 可以使用'script'标签上的DOM'Events'完成。 – FK82

+0

感谢您的输入,FK82。我只是想100%确定该脚本已加载。正如我所说的,在FF/Chrome中,onload和onerror完美工作。但在IE下,即使脚本url无效(或可能超时),readyState仍会返回加载。我想使用纯Javascript的原因是因为我想确保jQuery从CDN首先正确加载,然后使用jQuery来做东西。是的,我也发现这应该采用AJAX的方式。 (还没有尝试寿) – pepsi600

+0

请看看我的答案。您将能够使用AJAX/XHR('XMLHttpRequest')模式捕获各种HTTP错误。另外,我相信这在跨浏览器兼容性方面会更稳定。 – FK82

回答

5

根据您的评论,这里有一个如何使用动态添加脚本标签的示意图XHR(XMLHttpRequest):

var handleRequest = function() { //!! set up the handleRequest callback 

    if(this.status != undefined) { 

     /* do something with the status code here */ 

    } 

    if(this.readyState == 4) { 

      var script = document.createElement("script") ; 
       script.setAttribute("type","text/javascript") ; 
      var text = document.createTextNode(this.responseText) ; 
       script.appendChild(text) ; 

      var head = document.getElementsByTagName("head")[0] ; 
       head.insertBefore(script,head.firstChild) ; 

    } 

} ; 

var request ; //!! supposing you have a way to get a working XHR Object 

//.. set the XHR Object 

request.open("GET",url,true) ; 
request.overrideMimeType("text/javascript") ; 
request.onreadystatechange = handleRequest ; 
request.send(null) ; 

请记住,这只是给你明白我的意思的想法。从jQuery源代码判断一个工作示例必须更加精细。


链接:

+0

你的解决方案很有用,但要100%,它应该通过CORS处理来增强,因此它也可以在你的域之外加载脚本,否则你可以加载的脚本被限制在相同的原始策略:) – rupps

+0

谢谢。 (:在跨浏览器支持CORS实现方面你是对的,但跨域脚本访问的回退是使用SCRIPT标记 – FK82

-1

负载检测完成

[..] 一个网页建议设立一些事件处理程序的加载完成时将被调用。我们通过添加以下行至前面的代码:

var head= document.getElementsByTagName('head')[0]; 
var script= document.createElement('script'); 
script.type= 'text/javascript'; 
script.onreadystatechange= function() { 
    if (this.readyState == 'complete') helper(); 
} 
script.onload= helper; 
script.src= 'helper.js'; 
head.appendChild(script); 

这里我们设置了两个不同的事件处理程序在新创建的脚本标签。根据浏览器的不同,这两个处理程序中的一个应该在脚本加载完成后调用。 onreadystatechange处理程序仅适用于IE。 onload处理函数在Gecko浏览器和Opera上运行。

“this.readyState =='完整'”测试实际上并不完全工作。 readyState的理论上通过一系列状态云:

  • 0初始化
  • 1装载
  • 2加载
  • 3交互式
  • 4完整

但事实上,状态可能会被跳过。根据我对IE 7的经验,你会得到一个加载的事件或一个完成的事件,但不是两者都有。

它可能与您是否从缓存中加载有关,但似乎还有其他因素会影响您获得的事件。有时我也会加载或交互式事件,有时候我也不会。这可能是测试应该是“this.readyState =='加载'|| this.readyState =='完成'”,但是这有可能触发两次。

http://unixpapa.com/js/dyna.html

UPDATE

请,您可以sobstitute您script.onreadystatechange回调与此:

newjs.onreadystatechange = function() { 
    if (newjs.readyState === 'loaded' || newjs.readyState === 'complete') { 
     newjs.onreadystatechange = null; 
     alert('script is complete or loaded."); 
    } 

};

我注意到的另一件事是,你正在与==运算符进行字符串比较。 这可能会引起误解。改为使用===

+0

加油........你刚刚复制和粘贴?你的代码与我的完全一样(我的意思是结构),这就是我所说的...“readyState”永远不是“完整的”!我正试图弄清楚。 – pepsi600

+0

似乎没有办法知道如果加载或完成将被解雇。查看JavaScript模式“按需加载”。 作者写道: •在IE中,您订阅readystatechange事件并查找readyState “加载”或“完成”。所有其他浏览器都将忽略此项。 – user278064

+1

他说负载被触发,但即使脚本无效并失败(404等),它也会触发。他想知道如何检测。 –

10

我发现如何让脚本节点在IE7和IE8中变得'完整'。还有如何检测何时加载脚本时发生错误(node.onerror仅在IE9 +中工作)。 破解是在

  1. 不插入新创建的元素到DOM(一次)。
  2. 调用node.children属性并检查后面的node.onreadystate属性。如果属性更改为“完成” - 您已经加载脚本,它将更改为“加载” - 这是肯定的脚本加载错误。

试试看!

var node = document.createElement('script'); 
node.src = 'some-[un]existing-url.js'; 
node.type = 'text/javscript'; 

node.onreadystatechange = (function(node) { 
    return function() { 
     if (/loaded|complete/.test(node.readyState)) { 
      _finish(); 
     } 
    }; 
})(node); 

var _finish=function() { 

     if (node.readyState == 'complete') { 
      // insert node only after completing the request, though this is not necessary 
      var head = document.head; 
      head || (head = document.getElementsByTagName('head')[0]); 
      head.appendChild(node); 
      // call success function 
      _success(); 
      return; 
     } 

     var firstState = node.readyState; 

     // hack: calling 'children' property changes node's readyState from 'loaded' to complete 
     // (if script was loaded normally) or to 'loading' - if error detected 
     node.children; 

     // error detected 
     if (firstState == 'loaded' && node.readyState == 'loading') { 
      // custom error code 
      _error(); 
     } 
} 
+0

这是目前** **脚本注入**的最佳解决方案IE8 **带有成功和错误处理程序,通过AJAX加载脚本要好得多,因为通过脚本注入** AJAX CORS限制不适用**。 用'node.children'技巧找到好东西! Btw。 'var node = createNode( 'script','...... 当然是普通香草JavaScript 'var node = document.createElement('script');' ... – Semmel

+0

我不确定node.onerror在IE9中工作 – f1lt3r

+0

非常好,谢谢! –