锁定老帖子 主题:Ext 2.0 for JSVM
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-11-08
zhourenjian 写道 hax 写道 Java2Script是一个不同的模式,作为代码生成来说,上述问题不是很重要,但是对于本身的js框架来说,就不能接受了。 首先,异步加载和异步调用不是一回事。 其次,我自己也承认如果没有Java2Script提供Java匿名类的写法,手动写异步调用的javascript代码确实很痛苦,传递参数等等很繁琐。 但是有一点,异步调用并不是想象中的不可接受。当然,有工具支持最好;没有工具的话,确定一个模式,熟悉后就很好用了。 我个人觉得,以后异步调用会越来越多人用。 是的,我是指显式的异步加载(也就是以异步调用的方式加载)。所以问题很显然,它太繁琐。当然“它不像想象中的那样不可接受”,我们写Ajax不也一直在异步调用么。(除了我以前写了一半的Future模式,我打算过一段时间写完它。) 问题是像import这样基础的设施,如果要依赖一种特殊的代码模式,然后还会对测试等基本需求造成影响,那就是不可行的。如果不是这样的话,jsi和pies或者jsvm2至少import那部分都没得混了,因为杰出的jspkg已经全做完了(什么命名空间管理、同步加载、异步加载、伪异步加载……全部都做完了)。至少对我来说,我要重造轮子的理由,就是在于jspkg在这一点上的缺失。 工具是一个问题,除非你是大公司,否则强烈依赖于工具的技术肯定是不行的。 还有,异步我们越用越多,但是并非以手工异步调用(即callback)的方式。而是会切换到一些其他模式上去。比如我那未写完的Future模式(实际上最近我了解到这个东西的较理论化的名称叫做Call by Future,和Call by Value、Call by Reference、Call by Name、Call by Need等一样,都是一种传参计算的策略)。再比方,改用task管理或伪线程的形式。又比如在未来我们改用yield来以coroutine的形式编写此类程序。总而言之,不会出现callback满天飞的情况。 |
|
返回顶楼 | |
发表时间:2007-11-08
zhourenjian 写道 我个人觉得,以后异步调用会越来越多人用。
为什么这么认为呢? 异步调用的根本目的是什么?要解决什么问题? 假如今后浏览器支持js多线程了,同步只阻塞当前js线程,而不是阻塞浏览器导致假死; 假如宽带能千兆到户了,代码加载变得非常流畅; 假如还是现在目前这种ajax编程模式, 异步调用的意义再哪? |
|
返回顶楼 | |
发表时间:2007-11-08
wch3116 写道 zhourenjian 写道 我个人觉得,以后异步调用会越来越多人用。
为什么这么认为呢? 异步调用的根本目的是什么?要解决什么问题? 假如今后浏览器支持js多线程了,同步只阻塞当前js线程,而不是阻塞浏览器导致假死; 假如宽带能千兆到户了,代码加载变得非常流畅; 假如还是现在目前这种ajax编程模式, 异步调用的意义再哪? 同感,其实第一点就是最大的主因。第二点其实不重要,因为如果是必须的代码加载,那么不加载完成之前你总是不能操作的,异步或者同步的速度其实没有什么差别。 不过你说的主题仅限于脚本加载。其它领域还是需要异步的,只是我认为不会一直就采用原始的callback形式。目前看来最有前途取代callback模式的是coroutine。 |
|
返回顶楼 | |
发表时间:2007-11-08
hax 写道 wch3116 写道 zhourenjian 写道 我个人觉得,以后异步调用会越来越多人用。
为什么这么认为呢? 异步调用的根本目的是什么?要解决什么问题? 假如今后浏览器支持js多线程了,同步只阻塞当前js线程,而不是阻塞浏览器导致假死; 假如宽带能千兆到户了,代码加载变得非常流畅; 假如还是现在目前这种ajax编程模式, 异步调用的意义再哪? 同感,其实第一点就是最大的主因。第二点其实不重要,因为如果是必须的代码加载,那么不加载完成之前你总是不能操作的,异步或者同步的速度其实没有什么差别。 不过你说的主题仅限于脚本加载。其它领域还是需要异步的,只是我认为不会一直就采用原始的callback形式。目前看来最有前途取代callback模式的是coroutine。 第二假设是指当第一假设不成立的情况下,亦可以解决“同步”带来的问题。 “数据交互”采用异步方式还是经常用的。 我感觉,虽然目前 js 可以实现 coroutine 模式,但实现得比较复杂,另外也不是无条件的。 相比之下,不如 callback 或者observer 模式,形式简单,使用方便。呵呵 |
|
返回顶楼 | |
发表时间:2007-11-08
wch3116 写道 严格按照一个“类/对象”对应一个相同名称的文件的方式保存,也是指设计时“源代码”的文件组织方式,与工作时的装载属于不同的两个层面,不会造成之间的强耦合。(我对dojo的了解不够深入,通过一个插件对dojo的装载方法作切面,是否可使其与文件系统解耦呢?一个猜测:) )
如果是跟java一样的形式,那就应该没有问题。是否允许把多个类写到一个文件中去主要就成了开发习惯问题,不是很关键了。 dojo的问题用切面是不行的。耦合不是指其实现本身与文件系统的直接耦合,我所指的耦合,是指在客户代码中,必须使用dojo.require来指定所需要导入的resource。因为必须写在客户源代码中,所以根本无法解耦。注意,通常情况下,resource和module是同一的。也就是dojo.require('a.b')语句中,a.b可以被视作就是module。但是某些情况下同一个module会分在几个resource中(这个需求本身是合理的,因为namespace管理和载入本质上可以是分离的两个问题),所以会出现dojo.require('a.b'); dojo.require('a.b.extra')这样的情况。a.b和a.b.extra并不是两个module,而只是一个module的两个resource。 这样一种设计显然很confuse,实际上,所谓resource就是装载单元,而不是真正的namespace。但是resource的名字通常和namespace是一样或接近的,这让一般用户很难理解。为了让人容易理解,dojo还提供了require('a.b.*')这样的功能,实际上是通过一个__package__.js记录了一个a.b这个namespace下面有哪些resource,然后一一载入。注意,dojo 1.0发布了,我仔细看了一下,发现.*支持和__package__.js被废止了。 目前dojo的约定大体可能是这样的:a.b.MyClass是类,在a/b/MyClass.js中定义。而a.b.myfunctions表示一组方法,比如a.b.myunctions.f1(),在a/b/myfunctions.js中定义。特例是a.b._base,其所表示的一组通用方法是在a.b这个namespace下的,如a.b.f1(),但是这个规范并不统一,也有在a.b.common或者a.b._common中定义a.b.f1()的情况——唉,dojo真是乱。 总之dojo的问题非常明显,模块单元和命名空间不恰当的混淆在一起,而且客户端代码同时使用了这两个搅成一团的体系。 wch3116 写道 其实它还隐含了一个前提条件,就是:类似 public class 的才会被要求以单独文件保存,类似 inner class 的设计,可不必另存单独文件的。 现在看,实现js自动化加载管理有两种方式: 1. 约定一个“类/对象/模块”与代码文件路径的对应规则。 2. 在外部通过其它方式来描述这种对应关系。 我的观点是:基于高内聚低耦合的原则,逻辑单元对其它单元的引用和依赖不属于接口/协议的范畴,属于内部实现,应是不被外部了解和维护的。所以我倾向第 1 种方式。但为了实现将现有的lib按需加载而同时不侵入,2 也是一种好的方案,也可能是唯一的方案。 总结得太对了!我也非常赞同你对于“逻辑单元对其它单元的引用和依赖不属于接口/协议的范畴”的看法!!但是值得注意的是,在jsi和pies中(jsvm2当然也是),第一,仍然支持客户代码的$import指令(即逻辑单元本身的引用关系),只是这种方式下不能实现异步加载(或者要付出不爽的代价——例如需要“编译”过程)。而外部定义文件,也可以只定义逻辑单元本身的引用,而不直接定义装载单元的依赖关系(也就是,jsi只使用addObjectDependency的方式,或者pies缺省就是这样的),所以此外部文件就不那么“外部”了,而只是一种集中化的namespace定义方式。而对于传统js来说,大多数库根本没有namespace,所以通过外部文件定义namespace反而成为了一个非常重要的feature——可以无侵入的纳入第三方库!!!这一点,对于jsvm2来说也许不重要,因为jsvm2并没有把无侵入性作为项目的目标,而是致力于成为一个标准框架和标准的开发模式。(不知道我说的是否正确,呵呵。) 具体来说——先说jsi。jsi在缺省的时候,总是根据引用的full qualified名映射到一个目录下,然后找其下的__package__.js的定义文件,其中是对该目录下各个源文件中所定义的对象名字列表(其full qualified名自然就是目录名加上对象名如a/b/c.js中定义了C,则C的全名是a.b.C),以及该文件或对象对其他文件或对象的依赖。(描述不确的地方请jindw大人自己纠正。) 由此可见,jsi的方式,是直接映射namespace到文件系统的方式。同时,它并不支持独立的加载单元定义,而是直接把文件作为加载单元。当然,jsi具有一些通过配置改变这种缺省行为的方式,但是肯定不是主推的方式,jindw大人可自行说明之。:) 所以jsi是同时采用了你说的两种方式。但是其并不直接对应到类和对象(也就是说不是一个类一个文件——因为通常的js实践上没有这样的),而只对应到其上的目录。其中第二种方式用来加入文件与类的对应关系,以及互相的依赖关系。 pies的设计则采用另一种方式。不是从namespace映射到文件,而采取了以unit定义为中心的方式。任何时候不是直接加入一些新的namespace,而是首先需要在某个配置文件里写unit声明,大体如下: unit ('webapp1/myunit'). $import('net.sf.sarissa.Sarissa'). $export('mypackage.A'). $export('mypackage.B'). include('myunit-a.js'). include('myunit-b.js'). end; 这种定义方式乍看与dojo的方式有点类似。但是与之最大不同的是,我明确了unit不是namespace(诚如dojo的resource本质上并不是module),为此,我甚至不用a.b的形式来作为unit名称,而是采用a/b的形式。客户代码中$import的是namespace而不是unit,这就没有了dojo.require的概念错位了。 所谓unit,就是高内聚低耦合的模块,也是依赖性的单位。它的基本构成如下: unit所import的其他逻辑单元(full qualified name)。 unit所export(即定义,或者provide)的逻辑单元(full qualified name)。 unit的源代码(通常是文件的url)。 每个unit有自己的execution context,从而形成了一个独立的scope空间。因为unit是高内聚的,所以unit的源代码本身是不需要namespace的,其内的不带有namespace的名称会自动匹配到由import和export所声明的全名上。(当然要用的话也可以。)这样也可以同jsi一样做到无侵入的导入其他传统js类库。 由于已经定义了每个unit所定义的完整的名称(而不是像jsi那样,只定义了导出的不带namespace的名称),所以不是通过namespace映射目录,而是通过namespace寻找到定义它的unit,然后进行加载。 倒是unit在声明源文件url的时候,可以引入一些约定,比如,如果上面没有写include语句,就等价于include('myunit.js')。 这里有一点很重要,在绝大多数情况下,pies的用户不需要为定义依赖性做额外的事情。unit之间的依赖无需显式的定义,而是通过全名引用可以计算出来的。 除非有特别需求,比如可以让两个unit都export同样的全名,那么其他unit如果import这个名字,则也需要通过use语句来显式声明其到底优先使用哪一个unit的实现(或者不声明的情况下,按某种既定策略排定优先级)。这在功能上类似于jsi的addScriptDependence,但是在含义上是类似于jsi的setImplementation的,可以用来让不同unit使用一个类库的不同版本。 |
|
返回顶楼 | |
发表时间:2007-11-08
赞hax一个,洋洋洒洒数千言,都说的如此清楚明白。
hax的口才确实令人佩服,羡慕中。
|
|
返回顶楼 | |
发表时间:2007-11-10
呵呵,John Hax 之能言善辩已非第一次见识了,
前段时间在 TaoBao UED Blog 上的一篇“段正淳的css笔记”引发的讨论也很有意思--------------------
http://ued.taobao.com/blog/2007/08/12/css-notes/
|
|
返回顶楼 | |
发表时间:2007-11-21
哈哈..兄弟你的jsvm2有问题,而且有很大的问题.内存释放不到,你打开任务管理器,刷新你的按需加载的页面吧.看看你IE进程的内存吧
|
|
返回顶楼 | |
发表时间:2007-11-21
楼上的,测试的过程中顺便把IE窗口最小化试试
IE的垃圾收集烂怪不得别人。。。 |
|
返回顶楼 | |
发表时间:2007-11-21
itpsh 写道 哈哈..兄弟你的jsvm2有问题,而且有很大的问题.内存释放不到,你打开任务管理器,刷新你的按需加载的页面吧.看看你IE进程的内存吧
如果你想研究 dom leak, 建议去下载 Drip, firefox 的环境可以安装 Leak Monitor! |
|
返回顶楼 | |