学无止境

——把简单的知识用好,也把东西做的简单

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  21 随笔 :: 0 文章 :: 85 评论 :: 16万 阅读
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

      接触过相关知识的都知道,动态向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

posted on   JaiHo  阅读(4697)  评论(11编辑  收藏  举报
编辑推荐:
· 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,谁才是开发者新宠?
点击右上角即可分享
微信分享提示