11

我正在尝试在脚本完全加载后做一些事情。(IE8)

我用于测试的脚本: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');}
};

在我的情况下,“完整”永远不会显示,“加载”即使网址无效也会显示。所以没有办法判断一个脚本是否在 IE 下正确加载。

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

更新

好的,我刚刚阅读了一些文章,似乎 readystate 不是检测脚本加载的可靠方法。

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

4

3 回答 3

12

我发现了一个技巧,如何使脚本节点在 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();
        }
}
于 2013-09-17T02:54:07.427 回答
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 源代码来看,一个工作示例必须更加精细。


链接:

于 2011-08-05T08:27:10.540 回答
-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 == 'complete'” 测试实际上并不完全有效。readyState 理论上会经历一系列状态:

  • 0 未初始化
  • 1 次加载
  • 2 已加载
  • 3 互动
  • 4 完成

但实际上,可能会跳过状态。根据我使用 IE 7 的经验,您会得到一个已加载的事件或一个已完成的事件,但不能同时得到两者。

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

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

更新

拜托,你能用script.onreadystatechange这个来代替你的回调吗:

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

};

我注意到的另一件事是您正在与==运算符进行字符串比较。这可能会产生误导。改为使用===

于 2011-08-04T18:33:15.927 回答