让JavaScript文件并行载入
2008 11 15 03:17 AM 3125次查看
分类:JavaScript 标签:JavaScript
浏览器是按标签来解析的,每解析一段标签,就显示这段标签的内容。如果标签引入了外部文件(如图像),则会一边继续解析其他标签,一边继续下载该外部文件,直到载入完毕。
要注意的是,IE浏览器默认只会并行下载同一个域的2个文件,超过时就得等待。也就是说,如果你的网页上有10张图片,浏览器已经解析完img标签了,但只有2张图是立即下载的,后面8张会等到前面的下完才开始下载。
但浏览器在解析script标签时,为了确保JavaScript不会改变文档的内容,会停止所有页面元素的载入,直到这段script代码执行完毕。如果这个script标签引入了一个来自外部服务器的js文件,而这个服务器访问速度很慢,你页面上其他元素便都得等到这个js文件载入并执行完毕才能继续载入,这是多么无语的事…
我的网页就加了Google和Yahoo的统计代码,虽然放在页底了,但如果网速较慢,图像载入被阻塞了,而又解析到script标签了,图片便停止载入,直到Google和Yahoo完成统计。而由于这2个服务器也不是很稳定,整个过程经常要花费2~5秒,几乎占去了页面载入的大半时间,所以不得不让js文件载入时能并行处理其他内容。
script标签有个defer属性,会告诉浏览器这段代码不会改变文档的内容,使浏览器可以继续解析其他标签,加快载入速度。不过只有IE浏览器支持这个属性。
此外,用document.write输出一个JavaScript也不会使IE浏览器停止解析其他标签,不过在Firefox等浏览器上无效。并且,document.write是不符合XHTML标准的。
于是就得用到document.createElement这个方法了,例如下面这个例子就并行载入2个js文件:
<html>
<head id="head">
var js=new Array("http://www.google-analytics.com/ga.js","http://js.tongji.cn.yahoo.com/804924/ystat.js");
for (var i=0;i<js.length;++i) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = js[i];
document.getElementById('head').appendChild(script);
script = null;
}
</script>
</head>
<body>
</body>
</html>
不过还有个问题,并不是所有js文件都适合用这种方法载入。例如,若JavaScript文件中调用了document.write,那么很可能不能正确输出(各种浏览器的处理方式不同,Firefox就很可能不输出)。不过外部js一般也不会用这个函数。
再例如,如果有段JavaScript代码要用到这个js文件中的变量或函数,而这个文件尚未载入完毕,则会出现未定义错误。
最初我是想把那些JavaScript代码放在body的onload事件里,结果发现还是会出现未定义错误。
于是只能放在script标签的onload事件里了。但IE又不支持onload,而是自创了一个onreadystatechange事件,于是代码变成这样:
<html>
<head id="head">
<script type="text/javascript">
function f(){
//最后要执行的代码
}
</script>
<script type="text/javascript">
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://www.google-analytics.com/ga.js";
if (window.ActiveXObject){
script.onreadystatechange=f;
}else{
script.onload=f;
}
document.getElementById('head').appendChild(script);
</script>
</head>
<body>
</body>
</html>
这种方法理论上是可行了,但Firefox下会有很奇怪的问题。以这种方式加载JavaScript后,原页面的JavaScript变量可能会变成未定义。而Chrome的V8引擎是要事先编译JavaScript代码(而不是像其他浏览器解释执行),必须将JavaScript代码执行完毕,所以感觉这种方式对它是无效的(没有用工具测试)。
不过对于一般的JavaScript代码,这种方法确实大大提高了载入速度(IE和Firefox上用httpwatch插件测试过)。
目前就只研究了这么多,看以后是否能补充吧。
0条评论 你不来一发么↓