javascript动态加载三

摘要:
此函数用于在加载页面后执行所有加载。加载页面后,就绪功能不是窗口。如我们所想,加载本地JS。让我们先看看代码Using。async=函数(回调){asynQueue.push(回调)。可以理解,创建函数的queue_execAsn用于执行保存的回调函数。

先做两个链接:

javascript动态加载

javascript动态加载二

之前两篇都介绍了,通过动态加载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.onload,简单说只是页面中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="http://t.zoukankan.com/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下载(我只开了一个360的云盘 哈哈 简单嘛 呵呵 以本人的技术 还不至于去开一个github来 练习练习再说)

PS:希望下载的朋友 发现问题或者有更好的想法 提交于我 可以直接留言或者邮件我(sunjiawei1986@163.com) 谢谢

免责声明:文章转载自《javascript动态加载三》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇API网关实践-网易云轻舟微服务修改python的pip镜像源下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

01. go-admin的下载与启动

目录 一.介绍 二.新建空文件夹 三.获取后台源码并启动 1.下载编译go代码 2.配置命令到goland IDE ,debug启动 四.获取前端ui源码并启动 1.下载编译go代码 2.启动项目 ** go-admin 基于Gin + Vue + Element UI的前后端分离权限管理系统** 系统初始化极度简单,只需要配置文件...

[转]开发者必备的6款源码搜索引擎

From : http://news.cnblogs.com/n/184662/   英文原文:Open Source Matters: 6 Source Code Search Engines You Can Use For Programming Projects   在推动技术变革上,开源运动发挥了非常显著的作用。而 Linux 成功地将开源转换成...

asterisk 常用命令

1、运行调试常用命令 ./asterisk & #后台启动 ./asterisk -vvvc #启动asterisk 并尽量多的在后台显示调试信息 ./asterisk -r #连接asterisk控制台 set verbose #设置打印信息 2、asterisk控制台下常用命令 set reload #重新加载sip配置信息 sip s...

互联网产品怎么做数据埋点

在互联网产品上线之后,产品和运营人员需要即时了解产品的使用情况,有多少用户,用户使用了哪些功能,停留时长,使用路径。。。等。要回答这些问题,需要有数据,不能拍脑袋想当然。数据怎么得到呢?埋点就是采集数据的重要途径。 数据埋点不是新名词,在电脑网站出来之后就有统计工具,站长们很熟悉的谷歌、百度统计等工具,通过在HTML页面中嵌入它们提供的js代码实现数据采集...

Beeline里面执行hive脚本 函数nvl2()与replace()报错

Beeline里面执行hive脚本函数nvl2()与replace()报错 写脚本的时候是在impala里面执行的,都正常,但是转换为调度的时候是在beeline里面执行的 就会有问题了. 详情如下: replace函数: (去掉字符串里面所有空格) select replace(' hell o wor d ',' ',''); impala执行命令:...

SourceTree使用教程详解(连接远程仓库,克隆,拉取,提交,推送,新建/切换/合并分支,冲突解决)

前言:   俗话说的好工欲善其事必先利其器,Git分布式版本控制系统是我们日常开发中不可或缺的。目前市面上比较流行的Git可视化管理工具有SourceTree、Github Desktop、TortoiseGit,综合网上的一些文章分析和自己的日常开发实践心得个人比较推荐开发者使用SourceTree,因为SourceTree同时支持Windows和Mac...