动态创建脚本:readyState永远不会"完成"

pep*_*600 10 javascript readystate onreadystatechange

我试图在脚本完全加载后做一些事情.(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');}
};
Run Code Online (Sandbox Code Playgroud)

在我的情况下,"完成"从不显示,"加载"显示即使网址无效.所以没有办法判断脚本是否在IE下正确加载.

难道我做错了什么?为什么我永远不会得到完整的状态?

UPDATE

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

那么还有另一种方法吗?没有jQuery,但纯Javascript.

Yur*_*hev 11

我发现了如何让脚本节点在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();
        }
}
Run Code Online (Sandbox Code Playgroud)


FK8*_*K82 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) ;
Run Code Online (Sandbox Code Playgroud)

请记住,这只是为了让您了解我的意思.从jQuery源代码判断,一个工作示例必须更精细.


链接: