javascript动态加载三


Posted in Javascript onAugust 22, 2012

之前两篇都介绍了,通过动态加载JS文件或者说JS模块,是怎么一步一步实现。

首先是通过同步策略来实现模块加载与回调函数之间进行分离,接着是通过异步策略来实现模块加载与回调函数之间进行分离。

这一篇,主要是为了说说怎么优化异步策略,并且实现了随意加载(非任意顺序加载模块),页面Ready之后加载文件。先接一下上一篇遗留下来的问题

1、页面Ready之后进行加载

2、随意添加模块 进行加载

看第一个问题,这个问题其实还是比较简单的,主要是监听页面的DOMContentLoaded事件,这里就不多讲解,网络上搜索,一堆答案,直接上代码。

Using.ready = function(callback){ 
readyList.push(callback); if(document.addEventListener){ 
document.addEventListener("DOMContentLoaded",_ready,false); 
return; 
} 
// for IE 
var domReady = function(){ 
try{ 
document.documentElement.doScroll("left"); 
_ready(); 
}catch(ex){ 
setTimeout(domReady,1); 
return; 
} 
} 
domReady(); 
}

这一段代码中最难以理解的应该就是
document.documentElement.doScroll("left");

这里其实是IE的页面加载完毕事件,简单说就是IE里面标签加载完毕之后,是可以操作Scroll的,那就根据此原理来判断IE中页面是否加载完毕。

里面有一个_ready函数,这个函数就是用来做页面加载完毕之后执行所有加载的函数。贴一下代码

(编辑一下这一段:页面加载完毕Ready函数并不是我们思想中所认为的原生JS的window.load,简单说只是页面中DOM结构的加载完毕,具体信息,可自行百度google之)

var readyList = []; 
var _ready = function(){ 
while(readyList.length > 0){ 
var func = readyList.shift(); 
func(); 
} 
document.removeEventListener("DOMContentLoaded",_ready,false); 
}

下面就是本博文的重点了。还是先看一下代码
Using.asyn = function(callback){ 
asynQueue.push(callback); 
if(!_execAsyn.isRunning){ 
_execAsyn(); 
} 
}

还是通知Using要加载所需要的模块了,只不过里面加入了一个asynQueue数组和_execAsyn函数,他们的作用分别是

asynQueue是用来保存异步加载之后要回调的函数,没什么好解释的,是一个数组,可以理解为创建了一个函数的队列

_execAsyn是用来执行保存的那些回调函数的,即将所保存的函数逐一执行。看一下代码,代码中对每行的作用都进行了注释

var _execAsyn = function(){ 
// 创建一个变量来缓存需要执行的函数 
var func = null; 
// 如果队列中还有未执行的函数 则进行执行操作 
if(asynQueue.length > 0){ 
// 将_execAsyn函数修改为运行状态 
_execAsyn.isRunning = true; 
// 得到队列中第一个需要执行的函数 
func = asynQueue.shift(); 
// 调用异步加载模块Using.fn.script函数 并传入加载完毕之后需要执行的回调函数 
Using.fn.script(function(){ 
// 当前需要执行的函数 
func(); 
// 迭代_execAsyn 直到队列中没有需要执行的函数 
_execAsyn(); 
}); 
// 若队列中没有需要执行的函数 
}else{ 
// 则将_execAsyn运行状态改为false 
_execAsyn.isRunning = false; 
} 
}

这个函数,解释起来没什么特别的,说白了就是一个一个的执行需要执行的函数。那么,唯一需要注意的就是为什么操作队列的时候没有采用循环,而是使用迭代。那原因就是

1、队列中随时可能有新的函数需要执行,采用循环的话,可能执行不到最新的函数,因为函数总是插入到队列的尾部

2、 Using.fn.script是异步的,如果是循环的话,当前函数还没有执行完,可能下一个函数就已经进入了执行状态。那么,本身来说,同时执行几个函数,速率上可能会更高,为什么这里还要限制其多个函数并行呢?原因也很简单,因为每一次执行队列中的函数,可能都需要加载相应的模块,那么如果刚好友两个或者多个依赖相同模块的函数需要执行,而且并行执行,就可能出现同一个模块加载多次,并可能造成后续的函数执行不了,出现异常。

整个UsingJS的核心部分就这些。在其中我加入了Using.Class.create函数,这个函数在javascript动态加载文章的末尾有提到。

最后看一下页面使用情况:

<script type="text/javascript" src="js/using-0.4.2.min.js"></script> 
<script type="text/javascript"> 
Using("jq"); 
Using("UserView"); 
Using("jq"); Using.ready(function(){ 
Using.asyn(function(){ 
$("#panel").click(function(){ 
alert("by jquery"); 
}); 
}); 
}); 
Using.ready(function(){ 
Using("Http"); 
Using.asyn(function(){ 
var http = new Using.Modules.Http(); 
http.set("xxx"); 
http.show(); 
}); 
Using.asyn(function(){ 
var h = new Using.Modules.Http(); 
h.set("ooo"); 
h.show(); 
}); 
Using("jq"); 
Using.asyn(function(){ 
$("#panel").click(function(){ 
alert("loaded jquery"); 
}); 
}); 
}); 
</script>

这个一段代码,刻意进行重复加载,多次Ready事件和Ready之后进行Using导包。

有一个特别需要注意的地方

Using("Http"); 
Using.asyn(function(){ 
var http = new Using.Modules.Http(); 
http.set("xxx"); 
http.show(); 
}); 
// 假如在这个地方使用 
// var ht = new Using.Modules.Http(); 
// 是会报Using.Modules.Http不是一个constructor 
// 原因就是 
// 任何操作都是异步的,当执行此句时Using("Http")这个模块载入可能还没有完成 
// 这一点是仲谋给多个朋友进行使用时会犯的错误 总以为导包之后 万事大吉 
// 是的 本身应该是这样 导包之后 在任何地方都可以随意引用 
// 但是总得有个前提吧 那就是模块得加载完毕 
// 所以 还请将所有的代码都写在Using.asyn之内 
Using.asyn(function(){ 
var h = new Using.Modules.Http(); 
h.set("ooo"); 
h.show(); 
});

UsingJS下载
Javascript 相关文章推荐
[转]JS宝典学习笔记
Feb 07 Javascript
JavaScript 事件冒泡简介及应用
Jan 11 Javascript
js 静态动态成员 and 信息的封装和隐藏
May 29 Javascript
JavaScript使用ActiveXObject访问Access和SQL Server数据库
Apr 02 Javascript
js实现登陆遮罩效果的方法
Jul 28 Javascript
jQuery form插件的使用之处理server返回的JSON, XML,HTML数据
Jan 26 Javascript
学习掌握JavaScript中this的使用技巧
Aug 29 Javascript
基于JavaScript实现滑动门效果
Mar 16 Javascript
layui中使用jquery控制radio选中事件的示例代码
Aug 15 jQuery
详解js访问对象的属性和方法
Oct 25 Javascript
Node.js HTTP服务器中的文件、图片上传的方法
Sep 23 Javascript
微信小程序 轮播图实现原理及优化详解
Sep 29 Javascript
javascript动态加载二
Aug 22 #Javascript
javascript动态加载实现方法一
Aug 22 #Javascript
原生js写的放大镜效果
Aug 22 #Javascript
window.open不被拦截的实现代码
Aug 22 #Javascript
EASYUI TREEGRID异步加载数据实现方法
Aug 22 #Javascript
网页打开自动最大化的js代码
Aug 22 #Javascript
精心挑选的12款优秀的基于jQuery的手风琴效果插件和教程
Aug 22 #Javascript
You might like
浅析PHP中Session可能会引起并发问题
2015/07/23 PHP
PHP模板引擎Smarty内建函数详解
2016/04/11 PHP
PHP获取文本框、密码域、按钮的值实例代码
2017/04/19 PHP
ThinkPHP中Widget扩展的两种写法及调用方法详解
2017/05/04 PHP
swoole和websocket简单聊天室开发
2017/11/18 PHP
JavaScript constructor和instanceof,JSOO中的一对欢喜冤家
2009/05/25 Javascript
让IE8支持DOM 2(不用框架!)
2009/12/31 Javascript
Javascript中定义方法的另类写法(批量定义js对象的方法)
2011/02/25 Javascript
推荐10个超棒的jQuery工具提示插件
2011/10/11 Javascript
动态加载脚本提升javascript性能
2014/02/24 Javascript
jQuery中prepend()方法使用详解
2015/08/11 Javascript
jQuery实现带延迟效果的滑动菜单代码
2015/09/02 Javascript
jQuery给指定的table动态添加删除行的操作方法
2016/10/12 Javascript
使用 NodeJS+Express 开发服务端的简单介绍
2017/04/07 NodeJs
微信小程序中hidden不生效原因的解决办法
2017/04/26 Javascript
webpack开发跨域问题解决办法
2017/08/03 Javascript
浅谈Angular4中常用管道
2017/09/27 Javascript
python 文件和路径操作函数小结
2009/11/23 Python
Python构造函数及解构函数介绍
2015/02/26 Python
深入理解Python3中的http.client模块
2017/03/29 Python
Python的地形三维可视化Matplotlib和gdal使用实例
2017/12/09 Python
Python实现PS滤镜的万花筒效果示例
2018/01/23 Python
pandas实现选取特定索引的行
2018/04/20 Python
python 在指定范围内随机生成不重复的n个数实例
2019/01/28 Python
python实现扫描ip地址的小程序
2019/04/16 Python
Series和DataFrame使用简单入门
2019/11/13 Python
python 爬虫爬取京东ps4售卖情况
2020/12/18 Python
Luxplus荷兰:以会员价购买美容产品等,独家优惠
2019/08/30 全球购物
StringBuilder和String的区别
2015/05/18 面试题
心得体会范文
2014/01/04 职场文书
毕业生自荐书
2014/02/03 职场文书
酒店管理专业自荐信
2014/05/23 职场文书
新闻工作者先进事迹
2014/05/26 职场文书
学前班幼儿评语大全
2014/12/29 职场文书
2015年安全教育月活动总结
2015/03/26 职场文书
php 获取音视频时长,PHP 利用getid3 获取音频文件时长等数据
2021/04/01 PHP