Xhr异步按顺序加载script
2010-05-10 23:05 BlueDream 阅读(2093) 评论(1) 编辑 收藏 举报在同域的情况下.无阻塞异步加载js的比较完美的方法就是通过XHR eval动态加载解析外部js文件.但XHR的问题就是.无法保证加载顺序.只是哪个.js文件先加载完毕就先执行哪个.所以我们需要用个队列机制将其管理.提供顺序引入的功能.
<!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"> <head> <title> new document </title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> <script> if ( 'undefined' == typeof(System) || !System ) { var System = {}; } /** * Xhr -- Eval -- Order * xhr异步按顺序动态执行javascript */ System.Script = { // 存放script请求队列 queuedScripts: new Array(), /** * 引入执行.js文件函数 * @param (String) url 要引入执行的.js文件路径 * @param (Function) onload 当引入.js文件执行完毕后执行的函数 * @param (Boolean) order 是否要按顺序引入 */ load: function(url, onload, order) { // 队列长度 数组形式(自动递增) var iQueue = System.Script.queuedScripts.length; // 如果引入的多个.js文件有依赖关系,那么我们需要order为true if ( order ) { // 维护js请求相对应的数组队列.并分别赋予一张默认的hash表 var qScript = { response: null, onload: onload, done: false }; System.Script.queuedScripts[iQueue] = qScript; } var xhrObj = this.getXHRObj(); xhrObj.onreadystatechange = function() { // 获取xhr.并当xhr正确请求时 if ( xhrObj.readyState == 4 ) { // 如果是有顺序的话.那么要讲所有的请求都按顺序放入到队列中.并将每次请求返回的js文本赋给response键值 if ( order ) { System.Script.queuedScripts[iQueue].response = xhrObj.responseText; // 紧接着开始按照队列顺序注入js System.Script.injectScripts(); } else { // 如果不需要按照顺序执行的话.那么就谁先加载完毕谁就直接通过Script.text去执行.执行完毕后.如果指定了onload则运行onload var se = document.createElement('script'); document.getElementsByTagName('head')[0].appendChild(se); se.text = xhrObj.responseText; if ( onload ) { onload(); } } } }; xhrObj.open('GET', url, true); xhrObj.send(''); }, /** * 获取Xhr */ getXHRObj: function() { var methods = [ function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject('Xml2.XMLHTTP'); }, function() { return new ActiveXObject('Microsoft.XMLHTTP'); } ]; for ( var i = 0, len = methods.length; i < len; i++ ) { try { methods[i](); this.getXHRObj = methods[i]; break; } catch(e) {} } return methods[i](); }, /** * 用于按顺序引用JS.从队列中顺序注入javascript */ injectScripts: function() { // 开始循环注入js var len = System.Script.queuedScripts.length; for ( var i = 0; i < len; i++ ) { var qScript = System.Script.queuedScripts[i]; if ( !qScript.done ) { // 如果有一个script请求没有返回.那么就中断. if ( !qScript.response ) { break; } else { var se = document.createElement('script'); document.getElementsByTagName('head')[0].appendChild(se); se.text = qScript.response; if ( qScript.onload ) { qScript.onload(); } qScript.done = true; } } } } }; function init() { document.title += 'init function'; } System.Script.load('main.js', null, true); System.Script.load('sub.js', init, true); </script> </body> </html>
上面的代码就是一个具有队列性质的管理机制.
用法就是:
System.Script.load('main.js', null, true); System.Script.load('sub.js', init, true);
表示引入两个.js文件.顺序为先main.js然后再sub.js并且当sub.js执行完毕后会调用init方法.