標籤:情況 user loader request 串連 處理 r.js odi 非同步載入
指令碼載入和運行
當瀏覽器遇到一個<script>標籤時,無法預知javascript是否在<p>標籤中新增內容。因此,瀏覽器停下來,運行javascript代碼,然後繼續解析、翻譯頁面。
瀏覽器必須首先下載外部檔案的代碼,這要佔用一些時間,然後解析並運行代碼,這又要佔用一些時間。此過程中,頁面解析和使用者互動是被完全阻塞的。
將指令碼放在底部合并指令碼減少個數延遲指令碼(defer)
<script src="file1.js" defer></script>
defer屬性指明元素中所包含的指令碼不打算修改DOM,因此代碼可以稍後執行。對應的Javascript檔案將在<script>被解析時啟動下載,但代碼不會立即執行,直到DOM載入完成(在onload事件控制代碼被調用之前)。擁有defer屬性的檔案可以用頁面的其他資源一起並行下載。
相容性:只被IE 4+ 和FF 3.5+支援,在其他瀏覽器,defer屬性被忽略。
動態非同步載入指令碼
動態指令碼載入時非阻塞Javascript下載中最常用的模式,因為它可以跨瀏覽器,而且簡單易用。
var script = document.createElement(‘script‘);
script.type = ‘text/javascript‘;
script.src = ‘file1.js‘;
document.getElementsByTagName(‘head‘)[0].appendChild(script);
無論在何處啟動下載,檔案的下載和運行都不會阻塞其他頁面處理過程。甚至可以放在<head>部分。
當使用動態指令碼節點下載時,返回的代碼通常立即執行。當指令碼是“自運行”類型時,這一機制運行正常,但如果指令碼只包含供頁面其他指令碼調用的調用介面,則會帶來問題。此時,需要跟蹤指令碼下載完成並準備妥善的情況。使用動態<script>節點發出時間得到相關資訊:
function loadScript(url, cb) {
var script = document.createElement(‘script‘);
script.type = ‘text/javascript‘;
if(script.readyState) {// IE
script.onreadyStatechange = function () {
if(script.readyState === ‘load‘ || script.readyState === ‘complete‘) {
script.onreadystatechange = null;
cb();
}
}
}else {// Others
script.onload = function () {
cb();
}
}
script.src = ‘file1.js‘;
document.getElementsByTagName(‘head‘)[0].appendChild(script);
}
瀏覽器不保證檔案載入的順序,下面可以保證指令碼按順序下載並運行:
loadScript(‘file1.js‘,function () {
loadScript(‘file2.js‘, function () {
...
})
})
如果多個檔案的次序十分重要,更好的方法是講這些檔案按照正確的次序串連成一個檔案。
XHR 指令碼注入
var xhr = new XMLHttpRequest();
xhr.open("get", "file1.js", true);
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
var script = document.createElement ("script");
script.type = "text/javascript";
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
xhr.send(null);
優點:下載不立即執行的javascript代碼;同樣的代碼在所有現代瀏覽器中都不會引發異常。
缺點:Javascript檔案必須與頁面放置在同一個域內,不能從CDNs 下載。
推薦的非阻塞模式
推薦的向頁面載入大量指令碼的方法分為兩個步驟:第一步,包含動態載入javascript所需的代碼,然後載入頁面初始化所需的除javascript之外的部分。這部分盡量小,可能只包含loadScript()函數。當初始代碼準備好之後,用它來載入其餘的javascript。例如:
<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript">
loadScript("the-rest.js", function(){
Application.init();
});
</script>
【Hight Performance Javascript】——指令碼載入和運行