Google Groups Home
Help | Sign in
Recent pages and files
脚本按需导入(装载)的三种模式的对比    

何谓安需装载?

脚本程序 一般都是下载后执行,当脚本库非常庞大时,一次性下载起来非常费时,传统的解决方式是,按功能模块把脚本写在不同的文件中,页面上手动加入 script标签装载指定内容,但是这有一些缺点,类库的使用者需要知道没个脚本之间的关系,顺序要求等等,而不可能要求每个类库使用者都对其非常熟悉, 出错的可能性很大。于是很多框架开始支持导入指令,想使用什么一个导入函数就完了,不必一堆堆的script文件,不用小心翼翼的关注着他们的依赖关系。

安需装载的困境:

早 期安需装载(即时同步按需装载)有一个致命的弱点,浏览器阻塞问题。当按需装载某些类库时,通常通过XMLHttpRequest同步装载脚本文件实现, 这种情况下,在资源下载完成之前,浏览器将停止响应用户事件、停止页面重画操作。如果网速很慢,这段时间将非常让人讨厌,就像是死机似的。
以前的解决办法是,将常用类库资源直接打包到框架文件中,而按需导入就成了一个宣传的幌子,没有太多实际的价值。

安需装载的三种方式:

最简单的按需装载实现,通过XMLHttpRequest同步装载脚本文件实现。问题是,浏览器使用这种方式同步获取资源时将导致浏览器阻塞:停止响应用户事件、停止页面重画操作。所以,虽然编程最为简单,但是用户体验最差。

异步导入,不必多做解释,用户体验好,但是因为其异步特征,处理起来比较麻烦。

JSI通过动态预装载功能实现的一种同步获取资源的方法,虽然也是同步,但没有阻塞,可以算时兼顾易用性和用户体验的解决方按。缺点时有一定延迟,当前脚本标签中不可用。

使用方法

以一个JavaScript? 对象显示函数为例:

类库位置:example/dependence/show-detail.js

实现代码:

/**
 * 利用jsidoc中定义的JSON库(org.xidea.jsidoc.util.JSON)实现的一个用于显示对象细节的函数。
 * @param object 想查看的对象
 */

function showDetail(object){
       
var buf = ["对象信息如下:\n\n"];
        buf
.push(JSON.encode(object));
        confirm
(buf.join("\n"));
}

包定义代码:

this.addScript('show-detail.js','showDetail'
               
//装载前需要先装载JSON类库(事实上此处可以定义为装载后,先不理会那些复杂的优化手法吧^_^)
               
,"org.xidea.jsidoc.util:JSON"
               
);

即时同步按需装载

$import("example.dependence.showDetail");

var person= {}
person
.name='张三';
person
.location='北京';
person
.project='http://www.xidea.org/project/jsi/';
showDetail
(person)

异步按需装载

$import("example.dependence.showDetail",function(Code){
   
var person= {}
    person
.name='张三';
    person
.location='北京';
    person
.project='http://www.xidea.org/project/jsi/';
    showDetail
(person)
})  

延迟同步按需装载(无阻塞,JSI2.0+)。

<script>"../scripts/boot.js"></script>   
<script>  
$import
("example.dependence.showDetail");
</script>  
<script>  
var person= {}
person
.name='张三';
person
.location='北京';
person
.project='http://www.xidea.org/project/jsi/';
showDetail
(person)  
</script>  

JSI 导入函数参考

public <void|object|Package>  $import (<string>path , <Function|boolean|Object>targetocol , <boolean|Function>col)

     
导入指定元素(脚本、函数、类、变量)至指定目标,默认方式为同步导入,默认目标为全局对象(Global == window(html))。

       
//Example:
        $import
("com.yourcompany.ClassA")//即时装载--通过指定对象
        $import
("com/yourcompany/class-a.js")//即时装载--通过指定文件
        $import
("example.ClassA",MyNamespace)//指定装载目标
        $import
("example.ClassA",function(ClassA){alert("callback:"+ClassA)})//异步装载
        $import
("example/class-a.js",true)//延迟装载(可获得良好特性,需要编译支持或者服务端支持)

     
实现步骤:
          o
若元素未装载或依赖未装载,且为异步装载模式,先缓存需要的脚本资源
          o
若元素未装载或依赖未装载,且为同步非阻塞装载模式,打印预装载脚本(当前script标签的其他脚本可能继续运行,浏览器不同表现略有不同); 并且等待预装载脚本执行之后继续以下步骤
          o
若元素未装载或依赖未装载,装载之
          o
将该元素声明为指定目标的属性(默认目标为全局对象,这时相当于声明了全局变量)
     
全局对象的特殊性说明:

           
全局对象的属性同时也是全局变量,可以在任何地方直接使用,
           
也就是说:
            $import
函数调用时,默认(未指定target)导入成全局对象属性,等价于声明了一个全局变量。

     
该方法为最终用户设计(页面上的脚本),不推荐类库开发者(托管脚本)使用该函数,除非确实需要(如需要动态导入时)。类库开发者可在包中定义脚本依赖完成类似功能。



=== 参数 ===

      path

     
(package:Object|package.Object|package:*|package.*| scriptPath)
      targetocol

     
可选参数,指定导入容器。 当该参数未指定时,target为全局变量容器,这种情况等价于直接声明的全局变量。 当未指定第三个参数时,且target为函数或者boolean值时,target作为col参数处理,而target本身等价为未指定。 当该参数为有效对象时(instanceof Object && not instanceof Function),导入的元素将赋值成其属性;
      col

      callbackOrLazyLoad
可选参数,默认为null 如果其值为函数,表示异步导入模式; 如果其值为真,表示延迟同步导入模式,否则为即时同步导入(默认如此)。
Version: 
3 messages about this page
Apr 24 2007 by jindw
本来就是为解决部分浏览器的阻塞问题设计的,其他环境更本就没这个必要。府略这个参数即是。
Apr 24 2007 by johnhax@gmail.com
第三种方式的另外一个缺点是,必须依赖于script标签的实现方式,在不同浏览器中可能有不同的问题,更不要说非浏览器环境。
Apr 1 2007 by jindw
Click on
http://groups.google.com/group/jsier/web/%E8%84%9A%E6%9C%AC%E5%AE%89%E9%9C%80%E5%AF%BC%E5%85%A5(%E8%A3%85%E8%BD%BD)%E7%9A%84%E4%B8%89%E7%A7%8D%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%AF%B9%E6%AF%94
- or copy & paste it into your browser's address bar if that doesn't
work.
Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google