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 相关文章推荐
firefox下jQuery UI Autocomplete 1.8.*中文输入修正方法
Sep 19 Javascript
提升PHP安全:8个必须修改的PHP默认配置
Nov 17 Javascript
手机端转盘抽奖代码分享
Sep 10 Javascript
避免jQuery名字冲突 noConflict()方法
Jul 30 Javascript
JS判断指定dom元素是否在屏幕内的方法实例
Jan 23 Javascript
微信小程序 列表的上拉加载和下拉刷新的实现
Apr 01 Javascript
JavaScript实现随机数生成器(去重)
Oct 13 Javascript
浅谈Webpack 是如何加载模块的
May 24 Javascript
微信小程序实现基于三元运算验证手机号/姓名功能示例
Jan 19 Javascript
小程序从手动埋点到自动埋点的实现方法
Jan 24 Javascript
解决layui调用自定义方法提示未定义的问题
Sep 14 Javascript
vue自动化路由的实现代码
Sep 30 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
深入了解php4(2)--重访过去
2006/10/09 PHP
CURL的学习和应用(附多线程实现)
2013/06/03 PHP
php上传文件常见问题总结
2015/02/03 PHP
浅谈thinkphp5 instance 的简单实现
2017/07/30 PHP
在phpstudy集成环境下的nginx服务器下配置url重写
2019/12/02 PHP
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
2011/05/24 Javascript
TreeView 用法(有代码)(asp.net)
2011/07/15 Javascript
如何正确使用javascript 来进行我们的程序开发
2014/06/23 Javascript
JQuery中上下文选择器实现方法
2015/05/18 Javascript
使用JavaScript实现连续滚动字幕效果的方法
2015/07/07 Javascript
jquery实现简单Tab切换菜单效果
2020/07/17 Javascript
es6学习笔记之Async函数基本教程
2017/05/11 Javascript
利用angular、react和vue实现相同的面试题组件
2018/02/19 Javascript
jQuery实现点击旋转,再点击恢复初始状态动画效果示例
2018/12/11 jQuery
vue中过滤器filter的讲解
2019/01/21 Javascript
vue-router 按需加载 component: () =&gt; import() 报错的解决
2020/09/22 Javascript
vue实现井字棋游戏
2020/09/29 Javascript
vue项目配置 webpack-obfuscator 进行代码加密混淆的实现
2021/02/26 Vue.js
理解生产者消费者模型及在Python编程中的运用实例
2016/06/26 Python
python xml.etree.ElementTree遍历xml所有节点实例详解
2016/12/04 Python
Python基础教程之tcp socket编程详解及简单实例
2017/02/23 Python
Python中进程和线程的区别详解
2017/10/29 Python
解决django model修改添加字段报错的问题
2019/11/18 Python
Python文件操作函数用法实例详解
2019/12/24 Python
将自己的数据集制作成TFRecord格式教程
2020/02/17 Python
浅谈SciPy中的optimize.minimize实现受限优化问题
2020/02/29 Python
详解Django中views数据查询使用locals()函数进行优化
2020/08/24 Python
python通过cython加密代码
2020/12/11 Python
Window10上Tensorflow的安装(CPU和GPU版本)
2020/12/15 Python
CSS3的新特性介绍
2008/10/31 HTML / CSS
一套带网友答案的.NET笔试题
2016/12/06 面试题
标准化管理实施方案
2014/02/25 职场文书
小学二年级评语
2014/04/21 职场文书
婚礼嘉宾致辞
2015/07/28 职场文书
新西兰:最新留学学习计划书写作指南
2019/07/15 职场文书
如何使用SQL Server语句创建表
2022/04/12 SQL Server