博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
判定模块加载时是否存在循环依赖
阅读量:6933 次
发布时间:2019-06-27

本文共 2181 字,大约阅读时间需要 7 分钟。

循环依赖是所有语言的加载器都是大头的问题,除非你的模块都是像spring那么利用Ioc进行控制反转,那么出现循环依赖就是死结。对此,我们唯一能做的事是,在第一个循环依赖出现时就立即通知用户查看它们的依赖列表。

在AMD大肆普及动态加载的好处后,大家应该隐藏知道有两个方法干这事。一个定义模块的define方法,另一个是加载模块的require方法。

define方法的参数为define(name?, deps? ,factroy), 换言之模块名与依赖列表都不是必须的,require参数为require(names , callback)。当我们用require一组模块,将它们的返回值传到回调中前,它实质上做了许多事情,其中为了实现跨域加载脚本,我们使用了script标签进行加载。但这不重点。script标签加载回来的脚本有个严格的格式,里面就是一个define方法。这与JSONP非常相近。为了实现匿名模块,我们通常不使用第1个参数,但第2参数有时就不能省略。不过没有问题,我们可以从请求的URL中还原回模块名,因此最终还是得到三个参数,第二个参数依赖列表不存在,我们就置为空数组。当一个模块被加载回来,并且它的依赖列表为空,我们就可以说它是可用的。若一个模块存在依赖列表,那么当它的所有模块都可用时,它才可用。当两个模块存在循环依赖时,就变成你等我,我等你的状态,因此在每加载一个模块回来时,就检测它的依赖列表,不断回溯它的上级依赖,上上级依赖,但这些链中是否存在我们当前这个模块名。如果有就是循环依赖,立即抛错。这个检测我们也可以做些优化,这因为这是个图,经过的路径会非常复杂,我们可以跳过所有已发出请求但没有加载回来的模块或所有可用的模块。

//这些是定义在种子模块(核心模块)中var loadings = []; var modules = {};function define(name, deps, factory){    var el = modules[name] = {        deps:deps,        name: name,        factory:factory,        status: !deps.length//是否可用    }    if(!el.status){//踢进列队进行检测        loadings.push(el);    }    _checkDeps();    if( _checkCircle(deps, name) ){        throw new Error( name +"模块与之前的某些模块存在循环依赖")    }}function _checkCircle(list, nick){//检测是否存在循环依赖    for(var i = 0, name; name = list[ i++ ];){        var el =  modules[name];        if(el ){            if( el.name == nick || el.deps.length && _checkCircle(el.deps, nick)){                return true;            }        }    }}function _checkDeps(){//检测模块有没有加载成功    loop:    for ( var i = loadings.length, el; el = loadings[ --i ]; ) {        var deps = el.deps;        var ok = true;        for(var j = 0, name; name = deps[j++];){            if(!modules[name] || !modules[name].status){                ok = false;                continue loop            }        }        if(ok){            el.status = true;            loadings.splice( i, 1 );            _checkDeps()        }    }}//这是a.js的内容define("a",["b"])//这是b.js的内容define("b",["c"])//这是c.js的内容define("c",["a"])//方便自己用firebug肉眼确认console.log(modules)console.log(loadings)

上面只是判定依赖关系的代码,实质上模块加载系统非常复杂,分为拆分模块名,别名映射,转换为URL,创建加载用的iframe与script(iframe是为了更好地在opera与旧式IE判定死链),处理加载回来define方法的最后一个参数factory,还原它模块名,判定是否可用,是否循环依赖,如果存在依赖再加载它的依赖等步骤,具体搜我博客有关模块加载的其他文章。

转载地址:http://zkmjl.baihongyu.com/

你可能感兴趣的文章
cygwin(hadoop)卸载过程
查看>>
spring自动代理例子
查看>>
python ftp的上传和下载
查看>>
mysql(innodb)故障
查看>>
sed命令
查看>>
【date】显示系统当前时间
查看>>
p99延迟是什么
查看>>
Swift:一般继承父类的写法
查看>>
ssh使用公钥登录客户端设置
查看>>
月薪3万的程序员告诉你:这样工作才能拿高薪(转 IT之家)
查看>>
MySQL 文本文件的导入导出数据的方法
查看>>
2012来临 iPhone5摄像头深度解析
查看>>
memcached搭建缓存系统
查看>>
↑基于httpd反向代理tomcat集群商城的部署↑
查看>>
nginx日志切割
查看>>
OSPF 原理
查看>>
kvm(libivrt)bridge和nat模式共存互通
查看>>
查询SBO中修改OINV表的用户自定义存储过程
查看>>
zabbix 监控
查看>>
构建LAMP动态网站
查看>>