javascript库的延迟加载

如何控制js的加载顺序

如果只是简单的让js延迟加载,那只需要在页面尾部加上这样的代码:

 

var oHead = document.getElementsByTagName('HEAD').item(0);
	  var oScript= document.createElement("script");
	  oScript.id = id; 
	  oScript.type = "text/javascript"; 
	  oScript.src=src;
	  oHead.appendChild(oScript); 

 

 但这样加载有个问题,如果我立刻在后面调用这个延迟加载的js里面的方法或者变量就会报错,因为新加载的js还没执行完呢。并且document的onload方法不会等待这样的延迟js加载成功。

还有就是这样加载的js不能保证顺序。也就是不能保证先append的js先执行。如果后面的js依赖于前面的js,而前面的js比较大,加载延迟,则后面的js执行的时候就可能报错。

我在修改这个高亮代码的脚本的时候就遇到了这样的问题。

并不是所有的文章都有代码,并且每篇文章可能出现的代码语言不一样,需要根据内容加载不同的库。

shCore.js是核心js,需要先加载。然后是各个语言的js,具体取决于文章内容中出现的代码语言。如  shBrushJava.js,shBrushBash.js等。

后面这些js都依赖于shCore.js。当所有的js都加载完的时候,才能调用:

SyntaxHighlighter.highlight();

高亮代码。

参考了一些文章,终于弄出一个解决方案:

 

if(!window.BrushUtils) var BrushUtils = (function(){
	var ut = {
		baseurl:"",
		resources:[],
		brushMap : {js:"JScript",jscript:"JScript",javascript:"JScript",
					  bash:"Bash",shell:"Bash",css:"Css",actionscript3:"AS3",as3:"AS3",cpp:"Cpp",c:"Cpp",
					  csharp:"CSharp",groovy:"Groovy",java:"Java",javafx:"JavaFX",jfx:"JavaFX",
					  perl:"Perl",pl:"Perl",php:"Php",text:"Plain",plain:"Plain",py:"Python",python:"Python",
					  ruby:"Ruby",ror:"Ruby",rails:"Ruby",scala:"Scala",sql:"Sql",xml:"Xml",html:"Xml",xhtml:"Xml",xslt:"Xml"
		},
		parseBrush :function(){
			  var pres = document.getElementsByTagName("pre");
			  var brushs = new Array();
			  for(var i=0;i<pres.length;i++){
				  var pre = pres[i];
				  var className = pre.className;
				  className = className.toLowerCase();
				  var bush = null;
				  if(className.indexOf('brush:')==0){
					  brush = className.substr(className.indexOf(':')+1);
				   }else if(pre.getAttribute('name')=='code'){
					   brush = className;
					   pre.className='brush:'+className;
					}
					if(brush==null)
						continue;
					if(!eval("ut.brushMap."+brush)){
						pre.className='brush:text';
				   		brush = "text";
					}
					if(!brushs.contains(brush)){
						brushs.push(brush);
					}
			   }
			  return brushs;
		},
		loadLibs : function(_baseurl,_theme){
			var theme =_theme||"Default";
			var baseurl = _baseurl;
			ut.baseurl = baseurl;
			var brushs = ut.parseBrush();
			if(brushs.length==0)
				return;
			ut.loadStyle(baseurl+"styles/shCore.css");
			ut.loadStyle(baseurl+"styles/shTheme"+theme+".css");
			ut.resources.push({url:baseurl+'scripts/shCore.js',type:'js'});
			for(var i=0;i<brushs.length;i++){
				var lib = brushs[i];
				lib = eval("ut.brushMap."+lib);
				ut.resources.push({url:baseurl+"scripts/shBrush"+lib+".js",type:'js'});
			}
			ut.loadNext();
		},
		loadNext : function(){
			if(ut.resources.length>0){
				var resource = ut.resources.shift();
				//var tempUt = ut;
				var callback = ut.resources.length>0?function(){ut.loadNext();}:function(){SyntaxHighlighter.config.clipboardSwf = ut.baseurl+'scripts/clipboard.swf';SyntaxHighlighter.highlight();};
				if(resource.type=='js'){
					ut.loadJs(resource.url,callback);
				}else if(resource.type='css'){
					ut.loadStyle(resource.url,callback);
				}
			}
		},
		loadJs : function(src,callback){
				  var scriptTags = document.getElementsByTagName('script');
				  var oHead = document.getElementsByTagName('HEAD').item(0);
				  var script= document.createElement("script");
				  script.type = "text/javascript"; 
				  script.src=src;
				  script.onreadystatechange= function () {
							if (this.readyState == 'loaded' || this.readyState == 'complete') {
								callback();
							}
						}
				  script.onload= callback;
				  oHead.appendChild(script);
			   },
		 loadStyle : function(url){
				   var oHead = document.getElementsByTagName('HEAD').item(0);
					var style= document.createElement("link");
					style.type = "text/css";
					style.rel="stylesheet";
					style.href=url;
				   oHead.appendChild(style);
		  }
		};
	return ut;
	})();
 

 

调用:

 

  var syntaxhighlighter_url = "/scripts/syntaxhighlighter/";
   BrushUtils.loadLibs(syntaxhighlighter_url);
 

 

主要在于对script的加载成功事件的监听。ie的事件是onreadystatechange,firefox的是onload.把需要加载的js放在一个队列里,当前一个加载完成时候,从队列里取出下一个js,继续加载。

经过测试,这个方法在ie,firefox,opera上都可以使用。但据说Safari上是没这个事件的(未测试)。

本来想给样式表也加上事件监听,结果发现样式表加载成功在firefox下是不触发事件的,ie下可以。

参考网址:

http://unixpapa.com/js/dyna.html

Related Posts
微软对google说:不要把手伸到我媳妇怀里
终于在网上建了个家
Javascript(Ajax)开发测试工具
Javascript对象中使用setTimeout和setInterval的问题
css强制换行问题
javascript获取网页元素的最终样式


分类 : 脚本语言