本文让js动态加载,这样原本串行加载的js就变成并行了。
先看两个demo
demo_00:http://www.zhangjingwei.com/loadscript/demo_00/
再看demo_01:http://www.zhangjingwei.com/loadscript/demo_01/
很明显,demo_01中,js异步加载,没有阻挡图片的下载
让我们看看他是如何实现的。
var loadscript = { $$:function(id){return document.getElementById(id)}, tag:function(element){return document.getElementsByTagName(element)}, ce:function(element){return document.createElement(element)}, js:function(url) { s = loadscript.ce('script'); s.type = "text/javascript"; s.onreadystatechange = ready; s.onerror = s.onload = complete; s.src = url; loadscript.tag('head')[0].appendChild(s); function ready(){} function complete(){} } }
代码很简单,但我们忽略了一个很重要的问题。
虽然JS是异步加载了,但他们下载的顺序却不确定,万一B先与A加载,并且B调用了A内的函数呢?
这种情况在IE里经常出现。

2->1->3->4->6->5 就是这些js的加载顺序,现在我们想让他们变成1->2->3->4->5->6。怎么办?
我们增加一个回调,让他在第一个加载完成后再加载第二个。
var loadscript = { $$:function(id){return document.getElementById(id)}, tag:function(element){return document.getElementsByTagName(element)}, ce:function(element){return document.createElement(element)}, js:function(url,callback) { s = loadscript.ce('script'); s.type = "text/javascript"; s.onreadystatechange = ready; s.onerror = s.onload = callback; s.src = url; loadscript.tag('head')[0].appendChild(s); function ready(){ if (s.readyState == 'loaded' || s.readyState == 'complete') { callback(); } }; } }
这样写得到了我们想要的结果。
demo_02:http://www.zhangjingwei.com/loadscript/demo_02/
可是加载它的方法很臃肿。
loadscript.js('js1.js',function(){ loadscript.js('js2.js',function(){ loadscript.js('js3.js',function(){ loadscript.js('js4.js',function(){ loadscript.js('js5.js',function(){ loadscript.js('js6.js',function(){ }); }); }); }); }); });
改进一下 (同步加载)
demo_03:http://www.zhangjingwei.com/loadscript/demo_03/
var loadscript = { $$:function(id){return document.getElementById(id)}, tag:function(element){return document.getElementsByTagName(element)}, ce:function(element){return document.createElement(element)}, ls:function (url){ var req = this.createXmlHttp(); req.open('GET',url, false); req.send(null); //alert (req.status); if (req.status == 200 || req.status == 0) { window.eval(req.responseText); }; }, createXmlHttp: function (){ var xmlHttp; if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); }else if (window.XMLHttpRequest){ xmlHttp = new XMLHttpRequest(); } return xmlHttp; } }
js确实是串行下载了,可问题又来了,因为是同步加载又将图片的加载阻止了。
鱼与熊掌不可兼得么?有知道的朋友还请留言赐教。
干活去了!




suntear
八月 18th, 2009 @ 10:18
这个方法不错!多个css文件岂不是也可以这样了?以前听说过有人在服务器端高贵实现这种效果。
回复
Asins
八月 18th, 2009 @ 17:57
之前接触过LABjs这个小小的东西,作用就是加载JS文件,很方便,使用方法也比你这个要好些。
回复
张经纬
八月 19th, 2009 @ 09:35
@suntear
css也可以这样,其实这个用了好多年了,加载css我个人觉得没有多大意义,首先css并不会很大,另外css并不会组织并行下载,最后动态载入样式的时候,浏览器要重新渲染页面,其实挺耗费资源的。
不过js就要另外说了。
@Asins
我只是一个demo,抛砖引玉,并不完善,千万不能拿来就用,比如说我没有判断加载的是否重复等等。
回复
onion83
八月 20th, 2009 @ 18:06
思路很好,不过写起来有点浪费代码
loadscript.ls(‘js1.js’);
loadscript.ls(‘js2.js’);
loadscript.ls(‘js3.js’);
loadscript.ls(‘js4.js’);
loadscript.ls(‘js5.js’);
loadscript.ls(‘js6.js’);
做成一个干净的接口 loadscript.ls(‘js1′,’js2′,’js ….’); 多好
php 有一个叫auto_load的机制,核心的思想是用到的时候再加载.
例如 我调用的函数 package_a() ;能不能不考虑不需要加载那个js,反正只管调用.如果package_a() 又调用了 package_b() 那也自动再加载相关的文件.呵呵,这个就上升到一个编程的框架和包管理的级别了~可以多往这个方向思考一下.
回复
颜小城
八月 28th, 2009 @ 18:00
我不懂。
回复
小毛
八月 30th, 2009 @ 18:29
这个问题不是你可以考虑的,应该由浏览器开发人员来处理.
回复
张经纬 reply on 八月 31st, 2009 09:13:
@小毛
….大汗啊。
回复