动态载入JavaScript以及它的load事件

动态载入JavaScript

动态载入JavaScript非常简单,代码演示如下:

var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'test.js';
head.appendChild(script);

侦测JavaScript是否载入

我们常常用JavaScript来给其它元素添加load事件,但如果给一个script自身添加load事件还真不是一件容易的事。对于非IE的高级浏览器来说和一般元素添加事件方法是一样的,代码演示如下:

script.onload=function(){
	// do something
};

但对于IE来说则要复杂一点,不能直使用onload,而要使用onreadystatechange事件,通过onreadystatechange事件来判断script元素的readyState属性是否等于complete或者loaded,从而来确认script元素是否已经载入。代码演示如下:

script.onreadystatechange=function(){
	if(this.readyState == 'loaded' || this.readyState == 'complete'){
		// do something
	}
};

readyState具有以下几个状态值:

  1. 0 : uninitialized
  2. 1 : loading
  3. 2 : loaded
  4. 3 : interactive
  5. 4 : complete

注意:在IEcomplete或者loaded值是不会一起出现的,IE中会忽略一些状态,所以只需要判断它俩中的一个就可以了。

对于JavaScript不存在的处理

如果动态载入的JavaScript文件不存在的话,非IE浏览器会一直请求。在IE6IE7中,script的属性值readyState会返回一个loading值,但有时候延迟久了会返回一个loaded值。而在IE8中,script的属性值readyState仍然会返回一个complete,这个很奇怪。

最终方案

这里根据jQuery里面的代码修改了下,增加了载入错误的回调功能。代码演示如下:

/**
 * 动态载入 javascript 脚本
 * @author <a href="mailto:jon.ju@msn.com">Jon</a>
 * @param {Object} options 选项
 * @param {String} options.url 脚本的 url 地址
 * @param {Function} options.callback 脚本完成载入后回调的函数
 * @param {Function} options.error 脚本没有按时载入时回调的函数
 * @param {Number} options.time 请求超时时间,默认为 5 秒
 * @param {String} options.charset 脚本的编码
 */
function insertScript(options){
	var head = document.getElementsByTagName("head")[0] || document.documentElement,
	script = document.createElement("script");
	script.src = options.url;
	var done=false, // 是否完成脚本载入的标识
	timer; // 超时时间
	if (options.charset) {
		script.charset = options.charset;
	}

	script.onload = script.onreadystatechange = function() {

		if ( !done && (!this.readyState ||
				this.readyState === "loaded" || this.readyState === "complete") ) {
			done = true;
			// 如果有计时器,去除
			if(timer)clearTimeout(timer);
			if(options.callback)options.callback.call();

			// 防止 IE 下的内存泄漏
			script.onload = script.onreadystatechange = null;
			if ( head && script.parentNode ) {
				head.removeChild( script );
			}

		}
	};

	// 如果有错误回调函数,则超过一定时间就去除 script 的相关设置
	if(options.error){
		timer = setTimeout(function(){
			// 如果还没有完成
			if(!done){
				script.onload = script.onreadystatechange = null;
				if ( head && script.parentNode ) {
					head.removeChild( script );
				}
				if(options.error){
					options.error.call();
				}
			}
		},options.time || 5000);
	}

	head.appendChild(script);

}

假设有个在动态载入的test.js文件,里面的代码是这样的:

var myVar = 'OK';

载入代码为:

insertScript({
	'url':'test.js',
	'callback':function(){
		// IE 在文件不存在时也会触发 callback 函数,
		// 所以在这里要加个判断
		try{
			alert(myVar);
		}catch(e){
			alert('error');
		}
	},
	'error':function(){
		alert('error');
	},
	'time':1000
});

如果test.js存在,则会alert出“OK”,如果文件不存在IE8会立即alert出“error”,而其它常用浏览器过1秒后会alert出“error”。

此条目发表在 前端 分类目录,贴了 , , 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已被标记为 *

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>