现在很多同学们都在代码里模拟YUI3实现JavaScript异步模块化加载,也就是一个add,一个use..
YUI3里对模块的加载是串行模式,当没有combo配合时,看起来很不美观.
今天army8735同学提到这个事儿,发现还真是很多同学注意到了这一点.kissy本身的add use就是并行,也有同学对YUI3做了改进.
而进来我正在开发kissylite,是kissy的一个支持有限方法的子集,目标是用1.5k代码支持包管理和模块化管理,也遇到了这个问题.不如拿出来一起讨论.
我觉得kissy和yui3的问题是模块必须先注册,这样扩展性有一定的局限.
kissylite引入了包的概念,每一个包对应一个codebase,通过模块名就完全确定js所在路径.
那么在一个包内新增了模块之后,种子文件是不需要修改即可直接使用的.
这样增加循环依赖的风险a->b b->c c->a..
虽然这样循环了明显是程序逻辑错误,但是如果不加以防范,合作开发,多次上线,死循环漏到线上那打击是致命的..
我的解决办法很土..在env中有一个对象记录x=模块依赖哪些,又支持哪些..当出现x依赖x的时候就抛一个error出来好了.
以a->b b->c c->a为例use("a")时:
首先载入a,Env中:
依赖关系方面a->b,
支持关系方面b->a
然后载入b,Env中:
依赖关系方面:b->c,在通过上面的支持关系可以得到a同样依赖c,即a->b,c
支持关系方面:c->b;a,b->a
最后载入c,Env中:
依赖关系方面:c->a,再通过现有的支持关系能得到a->b,c,a 矛盾出现a依赖自己,报个错吧:循环依赖.
这种算法效率是很低的,但是先粗暴的实现一下用着,每次add可能都要访问相关依赖关系对象和支持关系对象,毕竟kissylite目标是给页面中的广告,这类小应用的,模块不会太多.算抛砖吧,求更好的算法.
另一方面这里看到a b c的加载是串行的,在开发完成后,每次use可以自动给出一个use的并行优化方案.
比如use("a"),在use成功后,可以控制台log一下,为了更好的并行加载模块,你应该use("a,b,c")..这样就可以边开发,边优化.
kissylite还解决了一个问题,就是add的时候永远不attach.
steve blog:Evolution of Script Loading给出的mobile上js加载方案,看到代码从按需加载进化到了按需执行的阶段.
对于模块化js简单一些,只要不先attach,只是一个单纯简单的add,耗费的精力少的多了.
大家可能担心use时候attach是不是慢了些,这个同样可以边开发边优化.
在开发一个页面,可以把常用的功能都跑一边,Env中包含你所有使用过的包.
那么就可以在domready后,不忙的时候把这些先use一遍...
这就有点
facebook primer的意思了,domready之前按需执行,domready之后选择性预热.
这里也说说异步执行单元的串行和并行.
这个老道正好在velocity china提到.
异步执行单元:asyncUnit(args,callback).所有可能需要等待一段时间才能收到结果的函数都可以叫异步单元.比如getScript(url,callback),use(mods,callback),还有一些动画回调,都是异步执行单元.
我们常常遇到很多异步执行单元,比如use(mods)这个场景.
按程序的业务逻辑,如果这些异步单元需要串行,则会遇到多层复杂的callback嵌套.
a(a1,function(resA){
b(b1,function(resB){
c(c1,function(resC){
///your code
})
})
})
这种代码不美观,越向内运行时scope链越长,性能也不好.
而按照程序业务逻辑,如果多个异步单元需要并行,则会遇到每次手动监测其他单元执行是否完成的情况
a(a1,function(resA){
window.resA = resA
if(window.resB){
c();
}
});
b(b1,function(resB){
window.resB = resB
if(window.resA){
c();
}
})
function c(){
//your code run after resA & resB returend
}
这种代码同样不美观,通过写死判断条件if(resA/B)每次手动检查其他相关异步单元执行情况.
kissylite增加了方法multiAsync(asyncers,callback),因为use时并发的情况较多,先解决并发这个问题,计划再增加一个参数,解决串行异步单元的问题..
最后附一下kissylite的readme,以及googlecode上临时预览地址:
http://tbad.googlecode.com/svn/trunk/kslite/testcase/test_loader.html
kslite为kissy的仅支持有限方法的子集:
这些方法包括log,mix,clone,extend,add,use,getScript,substitute
kslite为所在页面引入KSLITE全局对象.
相比于kissy,发生变化的方法如下:
add:任何时候只add,不attach.
use:不用add即可直接use,详见下面的包和模块管理.
包和模块管理:
模块名由包名,路径,文件名.三部分构成
如{packagename}-{path_0}-...-{path_n}-{filename}
包类似*.jar,每个包对应一个codebase即classesroot.在S.config.lt_pkgs中配置
是一个http地址,如果没有则以为kslite.js所在地址为base.
比如:
S.Config.lt_pkgs={
inf:"http://a.alimama.cn/kslite/",
test:"http://demo.taobao.com/tbad/kslite"
}
模块"inf-a"对应地址 http://a.alimama.cn/kslite/inf/a.js
模块"test-t-1"对应地址 http://demo.taobao.com/tbad/kslite/test/t/1.js
这样根据模块名称即可定位模块地址,所以不需要add预先注册模块即可直接use.
add不执行attach.只有第一次use的时候才执行attach.
add同样支持require.可以在载入js后根据require串行加载更多模块.(已处理循环引用风险,办法很土.)
暂时不支持use外部JS文件,如use("jquery.js");
性能方面考虑:
这种模式只要use中包含的模块足够,满足所有依赖,则可以保证所有模块并行load,否则可能存在串行情况.
开发时使用小模块模式,每一个正式产出,比如生成广告投放用inf.js,广告展现用showad.js应该手动combo.
因为在use时会按照require顺序attach,所以手动combo的代码不需要关心模块间顺序.
其他配置项:
kslite相关配置项,在局部变量kslite_config中,之后mix入S.Config
lt_b:kslite的base,推荐每个产出写死一个kslite的base地址,而不是通过currentScript获得.因为kslite不一定作为<script>节点静态引入
lt_pkgs:包路径信息,如上.
lt_t:时间戳比如20101129.js
lt_v:版本 如1.1.5 计划沿用kissy版本.
关于与kissy兼容性:
在页面存在同一版本的Kissy实例时,S.app("KSLITE")构建.
同时根据当前kissy的add模式,需要额外生成一段代码,将所需模块预先注册一下.
分享到:
相关推荐
考虑到有些模块无需在启动时载入,因此modJS提供了可以在运行时异步加载模块的接口:require.async (names, onload, onerror)names可以是一个模块名,或者是数组形式的模块名列表。当所有都加载都完成时,onload被...
listview异步加载,通过异步加载,listview可用从服务器下载下来的图片顶替预先加载的图片
包和模块管理:模块名由包名,路径,文件名。三部分构成 如 {packagename}-{path_0}-...-{path_n}-{filename}包类似 *.jar,每个包对应一个 codebase 即 classesroot。在 S.config.lt_pkgs 中配置 是一个 http 地址...
该源码由源码天堂IOS源码频道免费提供下载。实现高清晰大图的异步加载以及图片加载完成前首先加载预览图效果。加载高清晰大图通常需要一点时间,特别是...这份代码就是实现这种大图异步加载以及预先显示预览图的功能。
该算法利用 、 波的到达时间来计算震源位置,无需预先知道波速速度,只根据传感器的坐标及纵波、横波到各传感器时间差,即可实现弹丸地下起爆点的定位
该库将根据列出的依赖关系动态加载javascript文件(和函数),css和图像,同时还生成用于浏览器缓存版本控制的唯一文件名。 概述 Javascript代码通常取决于现有类,函数和元素的存在,尤其是document.body 。 由于很...
Anaconda 是一个 Python 的发行版,这意味着它预先集成了 Python 解释器、一系列重要的科学计算库(如 NumPy、Pandas、Matplotlib 等),并且通过 Conda 包管理系统,用户可以非常方便地安装、管理和切换不同版本的 ...
react-native-get-google-font:expo-font和@ expo-google-fontsome-font的替代方法,它允许裸身的react-native用户预先安装自己喜欢的expo-google-fonts,而无需依赖,并预先加载时间的
> 我们要展示一个ListView,ListView中的数据和布局都是我们网络获取的,我们预先并不知道。 以往的我们使用一个Listview一般都是为了展示一类布局相同的信息,这种情况下,我们可以通过adapter的getView()方法中...
仓库管理信息系统所需要实现的功能可以细分为以下几个模块:员工管理、仓库管理、货物管理、存储规则管理、货物进出控制、仓库需求生成和货物进出记录。 (1)员工管理模块 该模块负责管理信息系统所有参与仓库管理...
艾迈斯半导体预先发布 Nan EyeM 和 Nan EyeXS 微型摄像头模块.pdf
系统Web应用程序组织模块,定义将系统构建为标准WAR程序包的结构 10、datagear-webappembd 系统独立应用程序组织模块,定义将系统构建为独立可执行程序的结构 依赖: Java 8+ Servlet 3.0+ 编译: (执行单元测试...
例如有个storages模块,在require时需要和其他module共享数据。require("!storages");即可。 4.只在设计上遵循了AMD规范,但是使用上却使用了类似CMD规范。我和我的团队都喜欢在require时暴露出过程,会比较灵活。...
本文实例为大家分享了javascript实现图片预加载和懒加载的具体代码,供大家参考,具体内容如下 预加载 预加载是预先加载好后面需要用到的资源, 后面使用的时候直接去缓存里取。举个栗子, 比如一个网站的开场动画...
采用ThinkPHP + Bootstrap3制作,内置系统设置,上传管理,权限管理,模块管理,插件管理等功能,独有的Builder页面自动生成技术节省50%开发成本,先进的最终开发的支持让开发成本一降再降,致力于为个人和中小型...
数据结构实训题目:一、图书借阅管理系统二、 学生成绩管理系统(B)
第41部分 使用对象服务之标识关系中使用依赖实体与异步查询保存 第42部分 POCO之使用POCO 第43部分 POCO之使用POCO加载实体 第44部分 POCO之POCO中使用值对象和对象变更通知 第45部分 POCO之获取原始对象与手工同步...
它包含一个HTTP Server配置,该配置从预先分隔的过滤器和路由加载,一个JSON配置加载器,以及可以在其中组织处理程序,对象和实用程序功能的目录。 与Swift的兼容性 该项目的master分支当前在Ubuntu上使用Xcode 8.2...
随着技术和斜摄影测量技术的发展,斜摄影测量模型和底图的获取变得越来越方便和快捷。 底图数量的增加导致在加载倾斜摄影测量模型时3D GIS中过多的底图图块请求,从而降低了系统速度。 为了提高系统的运行速度,提出...
今天小编就为大家分享一篇vue+layui实现select动态加载后台数据的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧