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 。 之前把我的頭髮拉了出來。