读书人

模块的静态与动态循环依托

发布时间: 2012-10-18 13:46:56 作者: rapoo

模块的静态与动态循环依赖
场景:

?

循环依赖我是不支持的,但现实中似乎又确实需要循环依赖,例如前端的选择器场景 (ie<8):

?

首先实现了 DOM 模块来保证各个浏览器的兼容性以及 api 的易用性,其中包含必要简单的选择器逻辑

?

然后实现了高级选择器模块,但这并不是最常用,为了效率该模块是不放入核心 DOM 模块中的,而选择将它作为独立模块 :selector,显然 selector 模块依赖于 DOM 进行 dom 遍历.

?

S.add("selector",function(){},{requires:["dom"]});

?

而 DOM 中会进行判断是否当前选择器字符串过于负责而自己不能处理,需要高级选择器模块介入:

?

S.add("dom",function(S,Selector){  return {      querySelectorAll:function(q){           if(isAdvanced(q)){               return Selector.querySelectorAll(q);           } else{               // simple logic           }      }  };},{requires:["selector"]});

?

这时就形成了循环依赖

?

解决:

?

其实我们需要区分模块间到底是静态依赖还是动态依赖,静态依赖指模块的初始化就需要另一个模块参与,而动态依赖则是指直到模块的运行期才会需要调用另一个模块,对于静态循环依赖这个问题我觉得是无解的,而对于动态循环依赖则是完全可以绕过.

?

动态循环依赖可以参考类似 serviceloader 的做法,DOM 模块完全可以动态取得高级选择器接口的一个具体实现模块,而selector 模块实现接口并保证自己可以被找到即可:

?

DOM 模块:

?

S.add("dom",function(S){  return {      querySelectorAll:function(q){           if(isAdvanced(q)){               return S.ServiceLoader.load("selector").querySelectorAll(q);           } else{               // simple logic           }      }  };});

?

高级选择器模块仍可以依赖 DOM ,实现 querySelectorAll 接口(概念上,动态语言完全没必要),并注册自己即可.

?

而 ServiceLoad.load 完全可以和模块系统结合在一起,用户可以通过模块系统静态或动态载入一些高级附加模块,ServiceLoad.load 询问模块系统即可得到实现了高级选择器接口的具体模块.

?

?

?

refer:

?

static vs dynamic 1,2

?

circular dependency wiki

?

java.util.ServiceLoader api

?

?

?

1 楼 limu 2011-07-25 我也遇到这个问题,在seajs里遇到类似的问题.
把动态依赖的require改为require.async.
因为初始时一定是require过这俩,require.async的目标模块在调用时肯定已经被载入
所以调用时就是同步的,可以按同步的写法继续写余下的代码,而不用封装到回调中. 2 楼 yiminghe 2011-07-25 limu 写道我也遇到这个问题,在seajs里遇到类似的问题.
把动态依赖的require改为require.async.
因为初始时一定是require过这俩,require.async的目标模块在调用时肯定已经被载入
所以调用时就是同步的,可以按同步的写法继续写余下的代码,而不用封装到回调中.
哈,kissy 一直是通过 S.require("sizzle") 来解决的,不过看到后端语言的对应支持很踏实

读书人网 >Web前端

热点推荐