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 相关文章推荐
用jscript实现新建word文档
Jun 15 Javascript
ASP.NET中使用后端代码注册脚本 生成JQUERY-EASYUI的界面错位的解决方法
Jun 12 Javascript
javascript AOP 实现ajax回调函数使用比较方便
Nov 20 Javascript
JavaScript传递变量: 值传递?引用传递?
Feb 22 Javascript
详细解密jsonp跨域请求
Apr 15 Javascript
JS实现可编辑的后台管理菜单功能【附demo源码下载】
Sep 13 Javascript
微信小程序MUI导航栏透明渐变功能示例(通过改变rgba的a值实现)
Jan 24 Javascript
javascript面向对象三大特征之继承实例详解
Jul 24 Javascript
微信浏览器左上角返回按钮监听的实现
Mar 04 Javascript
微信小程序自定义yPicker组件实现省市区三级联动功能
Oct 29 Javascript
基于Cesium绘制抛物弧线
Nov 18 Javascript
element-ui封装一个Table模板组件的示例
Jan 04 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中eclipse 用空格替换 tab键
2013/06/24 PHP
php二维数组排序详解
2013/11/06 PHP
ThinkPHP打水印及设置水印位置的方法
2016/10/14 PHP
JavaScript null和undefined区别分析
2009/10/14 Javascript
JavaScript 动态创建VML的方法
2009/10/14 Javascript
javascript getElementsByTagName
2011/01/31 Javascript
js 关键词高亮(根据ID/tag高亮关键字)案例介绍
2013/01/21 Javascript
JQ技术实现注册页面带有校验密码强度
2015/07/27 Javascript
一个简单不报错的summernote 图片上传案例
2016/07/11 Javascript
如何用js实现鼠标向上滚动时浮动导航
2016/07/18 Javascript
JS控制div跳转到指定的位置的几种解决方案总结
2016/11/05 Javascript
BootStrap实现鼠标悬停下拉列表功能
2017/02/17 Javascript
vue打包相关细节整理(小结)
2018/09/28 Javascript
微信小程序基于picker实现级联菜单
2019/02/15 Javascript
基于javascript的拖拽类封装详解
2019/04/19 Javascript
浅入深出Vue之组件使用
2019/07/11 Javascript
vue使用map代替Aarry数组循环遍历的方法
2020/04/30 Javascript
JS canvas实现画板和签字板功能
2021/02/23 Javascript
python将xml xsl文件生成html文件存储示例讲解
2013/12/03 Python
python在指定目录下查找gif文件的方法
2015/05/04 Python
对python中的xlsxwriter库简单分析
2018/05/04 Python
详解python编译器和解释器的区别
2019/06/24 Python
正则给header的冒号两边参数添加单引号(Python请求用)
2019/08/09 Python
Python 高效编程技巧分享
2020/09/10 Python
详解pandas映射与数据转换
2021/01/22 Python
化学教师教学反思
2014/01/17 职场文书
求职者怎样写自荐信
2014/04/13 职场文书
租赁协议书范本
2014/04/22 职场文书
领导干部作风建设自查报告
2014/10/23 职场文书
营销计划书范文
2015/01/17 职场文书
新人入职感言
2015/07/31 职场文书
学习委员竞选稿
2015/11/20 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书
详解MySQL多版本并发控制机制(MVCC)源码
2021/06/23 MySQL
IIS服务器中设置HTTP重定向访问HTTPS
2022/04/29 Servers
教你使用RustDesk 搭建一个自己的远程桌面中继服务器
2022/08/14 Servers