Tôi biết câu trả lời của tôi hơi muộn cho câu hỏi này, nhưng, đây là một bài viết tuyệt vời trong www.html5rocks.com - Đi sâu vào vùng nước âm u của tải tập lệnh .
Trong bài viết đó, kết luận rằng liên quan đến hỗ trợ trình duyệt, cách tốt nhất để tải động tệp JavaScript mà không chặn kết xuất nội dung là cách sau:
Xem xét bốn tập lệnh có tên script1.js, script2.js, script3.js, script4.js
thì bạn có thể thực hiện bằng cách áp dụng async = false :
[
'script1.js',
'script2.js',
'script3.js',
'script4.js'
].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
Bây giờ, Spec nói : Tải xuống cùng nhau, thực hiện theo thứ tự ngay khi tất cả tải xuống.
Firefox <3.6, Opera nói: Tôi không có ý tưởng gì về điều này async, đó là gì, nhưng thật ra tôi đã thực thi các tập lệnh được thêm vào thông qua JS theo thứ tự chúng được thêm vào.
Safari 5.0 cho biết: Tôi hiểu về mối quan hệ của Async, nhưng không hiểu cách đặt nó thành Hồi sai với JS. Tôi sẽ thực thi các tập lệnh của bạn ngay khi chúng hạ cánh, theo bất kỳ thứ tự nào.
IE <10 nói: Không có ý tưởng nào về dịch vụ as async, nhưng có một cách giải quyết bằng cách sử dụng trên mạng onreadystatechange.
Mọi thứ khác nói: Tôi là bạn của bạn, chúng tôi sẽ làm điều này bằng cuốn sách.
Bây giờ, mã đầy đủ với IE <10 cách giải quyết:
var scripts = [
'script1.js',
'script2.js',
'script3.js',
'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];
// Watch scripts load in IE
function stateChange() {
// Execute as many scripts in order as we can
var pendingScript;
while (pendingScripts[0] && pendingScripts[0].readyState == 'loaded') {
pendingScript = pendingScripts.shift();
// avoid future loading events from this script (eg, if src changes)
pendingScript.onreadystatechange = null;
// can't just appendChild, old IE bug if element isn't closed
firstScript.parentNode.insertBefore(pendingScript, firstScript);
}
}
// loop through our script urls
while (src = scripts.shift()) {
if ('async' in firstScript) { // modern browsers
script = document.createElement('script');
script.async = false;
script.src = src;
document.head.appendChild(script);
}
else if (firstScript.readyState) { // IE<10
// create a script and add it to our todo pile
script = document.createElement('script');
pendingScripts.push(script);
// listen for state changes
script.onreadystatechange = stateChange;
// must set src AFTER adding onreadystatechange listener
// else we’ll miss the loaded event for cached scripts
script.src = src;
}
else { // fall back to defer
document.write('<script src="' + src + '" defer></'+'script>');
}
}
Một vài thủ thuật và thu nhỏ sau, nó là 362 byte
!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
"//other-domain.com/1.js",
"2.js"
])