接触过相关知识的都知道,动态向DOM中添加js的script标签时,在各种浏览器下会有不同的表现。
这里只讨论支持并行下载的浏览情况,大致分为两种,一种是按加向DOM树中加的顺序执行,另一种按下载完成的先后顺序执行;这样如果js文件间有依赖关系的话,且是按下载顺序执行,且在没有缓存的情况下就会报错(通常的情况下第一次执行会报错,http返回状态200,如果缓存未禁用,http状态是304,就不会报错了)
而ie就是按http下载完成的先后顺序执行js代码的,首先看下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" lang="zh-CN"> < head > < meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> < title >Model</ title > < meta http-equiv="Content-language" content="zh-CN" /> </ head > < body > < div id="page"> </ div > <!-- Page end! --> < script type="text/javascript"> //<![CDATA[ var js = document.createElement('script'); js.type = 'text/javascript'; js.src = 'alert.js'; if(js.readyState){ js.onreadystatechange = function(){ if (js.readyState == "loaded" || js.readyState == "complete"){ alert(js.readyState); document.getElementsByTagName('head')[0].appendChild(js); } }; }else{ document.getElementsByTagName('head')[0].appendChild(js); js.onload = function(){ alert('loaded not in ie!'); }; } //]]> </ script > </ body > </ html > |
其中动态加载的alert.js文件中内容为:alert('in alert.js');
经过测试(ie8),可以发现弹出的内容先后为:loaded、in alert.js、complete
查资料可得ie下向DOM中添加script时有onreadystatechange事件(其它浏览器有onload事件),而事件中js.readyState的状态变化为:loading(下载中)、loaded(下载完成)、complete(代码执行完成)
从代码中可以看出我是在事件中才向DOM中添加创建的scrip结点的……
因此可以得出ie在创建scrip结点并给src赋值时就开始有http下载了,这与其它浏览器完全不同(其它浏览器是要把script结点加到DOM中才会有http下载的),而把scrip结点向DOM树中添加后才开始执行代码。
有了这些结论我们就可以解决ie下并行下载顺序执行的问题了;有两种方案:一种是边下载边顺序执行,另一种是全下载完再顺序执行。
两种各有好处,这里给出后一种情况的代码(loader.js):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /* 来自博客园:http://www.cnblogs.com/jaiho/archive/2011/09/12/2174131.html * Author: JaiHo */ ( function (window){ var DOMLoader = ( function (){ var DOMLoader = function (){ return new DOMLoader.prototype.init(); }; DOMLoader.prototype = { jsList:[], js_all:0, loaded_js:0, head:document.getElementsByTagName( 'head' )[0], init: function (){ }, create_node: function (src){ var js = document.createElement( 'script' ); js.type = 'text/javascript' ; this .bindWait(js); this .jsList[ this .jsList.length] = js; js.src = src; }, loadJS: function (list){ len = list.length; for ( var i=0; i<len; i++){ if ( i==len-1 ) this .js_all = len; this .create_node(list[i]); } return this ; }, bindWait: function (js){ if (arguments.callee.caller!== this .create_node) return ; var that = this ; if (js.readyState){ js.onreadystatechange = function (){ if ( js.readyState == 'loaded' ){ that.loaded_js++; if ( that.js_all == that.loaded_js ){ that.head.appendChild( that.jsList.shift() ); } } if ( js.readyState == "complete" ){ js.onreadystatechange = null ; if ( that.jsList.length ){ that.head.appendChild( that.jsList.shift() ); } } }; } else { js.onload = function (){ alert( 'not in ie!' ); }; } return this ; } }; DOMLoader.prototype.init.prototype = DOMLoader.prototype; return window.DOMLoader = DOMLoader; })(); })(window); |
测试例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > <html xmlns= "http://www.w3.org/1999/xhtml" xml:lang= "zh-CN" lang= "zh-CN" > <head> <meta http-equiv= "Content-Type" content= "text/html; charset=gb2312" /> <title>Loader</title> <meta http-equiv= "Content-language" content= "zh-CN" /> <style type= "text/css" media= "all" > </style> </head> <body> <div> </div> <script type= "text/javascript" src= "loader.js" ></script> <script type= "text/javascript" > //<![CDATA[ window.onload = function (){ var loader = DOMLoader(); loader.loadJS([ 'json.js' , 'jquery-1.5.min.js' , 'test.js' ]); }; //]]> </script> </body> </html> |
可以看出加载的3个js文件是并行下载的。
对于其它浏览器有动态加载js文件的并行下载和顺序执行问题的情况,目前还没有相对完美的解决方案(如果有了请指教一下。。),单从这个方面,个人觉得ie的这个onreadystatechange事件方案相对好些。
P.S.:转载请注明出处,谢谢!JaiHo
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?