2011-08-04 45 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

非常好,謝謝! –