javascript - 可以信任script.readyState來檢測動態腳本加載的結束嗎?




scripting dynamic (4)

我使用動態腳本加載來減少初始頁面加載的持續時間。 為確保可以訪問腳本定義的函數和對象,我需要確保腳本已完全加載。

為此我開發了自己的Javascript庫 ,因此對該主題進行了大量研究,研究了它在不同庫中的完成情況。 在與此問題相關的討論中, LABjs的作者Kyle Simpson表示:

LABjs(以及許多其他加載器)在所有腳本元素上設置“onload”和“onreadystatechange”,知道某些瀏覽器會觸發一個,有些瀏覽器會觸發另一個...

撰寫本文時,您可以在當前版本的jQuery中找到此示例,v1.3.2

// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
    if ( !done && (!this.readyState ||
    this.readyState == "loaded" || this.readyState == "complete") ) {
        done = true;
        success();
        complete();

        // Handle memory leak in IE
        script.onload = script.onreadystatechange = null;
        head.removeChild( script );
    }
};

這是最先進的技術,但在分析Opera 9.64中的一個奇怪的行為時,我得出的結論是,使用這種技術,onload回調過早被解雇了。

我會在回答這個問題時發表自己的研究結果,並希望收集社區的進一步證據和反饋。


Chrome中的結果相似。

不接受......

只是onload和onerror。


在Firefox,Safari和Chrome中,會調用onreadystatechange處理程序。

我創建了一個簡短的測試用例,創建了一個只有onreadystatechange處理程序集的動態腳本:

<script type="text/javascript" language="javascript">
bezen.log.info(new Date(),true);
bezen.log.info(navigator.userAgent,true);

// Activate logs
bezen.log.on();
bezen.log.info('Test for script.readyState behavior started');

var script = document.createElement('script');
script.src = 'test1.js';
script.onreadystatechange = function(){
  bezen.log.info('readystatechange: '+script.readyState);
};
document.body.appendChild(script);
bezen.log.info('Added script with onreadystatechange handler');
</script>

我在Firefox 2,Firefox 3,Firefox 3.5,Safari 3,Safari 4和Chrome 3中的本地文件上執行了測試,並得到了類似的結果(這裡記錄在FF 3.5中的日誌):

Fri Dec 18 2009 17:53:58 GMT+0100
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6
Test for script.readyState behavior started
Added script with onreadystatechange handler
test1.js: Start
test1.js: Start of closure
test1.js: End of closure

onreadystatechange永遠不會被調用。 在這些瀏覽器中,只有onload偵聽器對於檢測腳本加載的結束很有用,不需要onreadystatechange。


在Opera中,script.readyState屬性不可信任。 例如,在腳本在Opera 9.64中運行之前,可能會觸發readyState“loaded”。

我在Opera 9.64和Opera 10中執行了相同的測試 ,結果不同。

在Opera 9.64中,onreadystatechange處理程序在腳本運行之前和之後一次被觸發兩次。 readyState屬性在兩種情況下都被“加載”,這意味著無法信任此值來檢測腳本加載的結束:

# Fri Dec 18 2009 17:54:43 GMT+0100
# Opera/9.64 (Windows NT 5.1; U; en) Presto/2.1.1
Test for script.readyState behavior started
Added script with onreadystatechange handler
readystatechange: loaded
test1.js: Start
test1.js: Start of closure
test1.js: End of closure
readystatechange: loaded

在Opera 10中,onreadystatechange處理程序仍然使用值“loaded”被觸發兩次,但是在腳本運行後的兩次:

# Fri Dec 18 2009 18:09:58 GMT+0100
# Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.10
Test for script.readyState behavior started
Added script with onreadystatechange handler
test1.js: Start
test1.js: Start of closure
test1.js: End of closure
readystatechange: loaded
readystatechange: loaded

這些不同的行為表明onreadystatechange不是檢測Opera中腳本加載結束的可靠方法。 由於Opera還支持onload偵聽器,因此應該使用其他機制。

根據這些測試的結果,onreadystatechange只應用於檢測Internet Explorer中腳本加載的結束,不應在其他瀏覽器中設置。


我發現Internet Explorer(在9中測試)在readyState ==='loaded'時,並不總是準備好你的腳本。 我已成功使用此事件處理程序(當然是9) onactivate 。 之前把我的頭髮拉了出來。





labjs