`
trydofor
  • 浏览: 147213 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

JS 异步按需载入和异步编程总结

阅读更多
JS 异步按需载入和异步编程总结
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 授权: 共同创作2.0
- 作者: trydofor

本文使用了[[a9text => http://a9text.sf.net]]格式.
目标读者为,有一定js基础,并对异步按需载入有需求的人群.

0. 目录
^^^^^^^
[[<=$INDEX]]

1. 为什么异步按需载入
^^^^^^^^^^^^^^^^^^^^^
在web应用上,经常会根据需要来载入不同的JS/CSS/TEXT/HTML等.
在粗放型web开发,被用户体验取代的今天,按需载入也被用来榨干代码中的油水.
之所以我过多的关注按需载入,是因为sourceforge.net的访问速度有点可怜.
而且我一直努力的a9text有太多的area需要实时载入parser和render.

开发和本地使用,使用了XMLHttpRequest同步,但web应用中同步就等于死机
曾经和JSI的金大卫调侃说:知道浏览器厂商,啥时候能改善同步的体验不?

异步按需载入迫在眉睫,但JSI又不适合a9text.
JSI的着眼点在于已知,而a9text在于运行时和线程功能.
尽管老金告诉我JSI2.0瘦身版才5k,代码才500行.
无奈,只能自力更生 ...

2. 如何异步按需载入和异步编程
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
js不支持线程功能,更不用指望sleep和wait等功能.异步编程的不可预测性在js上徒增.
(http://www.neilmix.com/narrativejs/doc/设想不错,大家可以学习下)
挣扎过程中,考虑过timeout和interval,但不是最佳,也不是有效的方法.
解铃还得系令人,着眼点还得回到XMLHttpRequest的使用上来.

为此,a9text废除了a9engine,写了个专一的a9loader,用来提供异步开发的模式.
首先亮相的是a9loader提供了以下2个异步载入和编程的方法.
...........................................................
void A9Loader.asyncImportClass(String clzz)
    async import an js and export like java
    @param clzz (String) eg:'com.trydofor.a9text.parser.a9text'

void A9Loader.runAfterImport(Function func)
    run the func when all class imported
    @param func (Function)
...........................................................
asyncImportClass 用来 异步载入/初始化/包隔离/公共化 一个js类
runAfterImport 用来执行所有等待import完毕后的方法.

================== js : example ========================
A9Loader.asyncImportClass('com.trydofor.a9text.parser.a9text');
A9Loader.asyncImportClass('com.trydofor.a9text.render.html.a9text');

A9Loader.runAfterImport(function(){
    for(var i=0; i<a9PreText.length;i++){
        var a9dom = new A9Dom(null,A9Dom.type.root); //com.trydofor.a9text.A9Dom
        a9dom.setText(a9PreText[i]);
        a9dom.putInfo(A9Dom.type.root$path,A9Loader.getPagePath());
        a9DomHtml[a9dom.getId()] = a9PreHtml[i];
       
        new A9TextParser().parse(a9dom,function(){
            new A9TextRender().render(a9dom,function(){
                var a9htm = a9dom.getData();
                var preHtml = a9DomHtml[a9dom.getId()];
                var prePos  = bodyHtml.indexOf(preHtml);
                var headPos = bodyHtml.lastIndexOf('<',prePos);
                var footPos = bodyHtml.indexOf('>',prePos+preHtml.length)+1;
                bodyHtml = bodyHtml.substring(0,headPos) + a9htm + bodyHtml.substr(footPos);
                if(document.body) document.body.innerHTML="";
                document.write(bodyHtml);
                document.close();
            });
        });
    }
});
========================================================
上面的代码中,runAfterImport中还间接的调用了runAfterImport.
但结果都是缓存在一个队列中,等待import结束后顺序执行.

实现手法是这样的:
有一个task队列,里面有引用计数和几个队列.
发送一个async request的时候,计数加1,callback的时候,计数减1
同时呼叫一个检查计数的方法.
当最后一个callback执行时,计数等于0,于是开始处理各种队列.

3. 应用范围与不足
^^^^^^^^^^^^^^^^^
本应用属于另类,仅在特殊场合应用或学习使用,
一般的web开发,最好使用script tag或通常的ajax手法.

因为没有使用timeout和interval,框架完全基于一个基本假设,
就是所有async请求都能正常返回,如果其中有一个出现问题,
runAfterImport中排队的方法将永远不被执行.

其中的危险,主要来自浏览器的缓存,网络条件.

异步JS开发,请尽量回避.
希望a9loader和本文对需要的人有帮助.
分享到:
评论
10 楼 hax 2008-04-02  
我是指runAfterImport的行为和onload比较类似,runAfterImport要等到所有依赖的包都载入完毕再执行,这与onload要等到所有资源都load完成才执行的意思是类似的。呵呵。
9 楼 trydofor 2008-04-01  
实际情况要复杂,不信,你可以访问下a9text.sf.net,看看源代码(右键即可以啦),基本上onload这个时间点,还没有载入大部分需要的js. onload不能解决的问题是,解析文档过程中,需要根据area名在配置文件中找到实现类并异步载入相关类,然后把结果合并到a9dom中,这个过程是比较难以把握的.

虽然异步载入,不是实际意义上的多线程,但是在这种竞争条件下,思考问题的方式和处理的方法,都会变得很诡异,要保证代码的可读性,是个比较棘手的问题,至少我在a9text的设计和编码过程中这样感想,js真是比较郁闷的事情
8 楼 hax 2008-03-30  
“runAfterImport的执行时机,有点特别,不同于onload. ”

我觉得正好合适啊。因为document onload是要等待所有资源(比如图片)的onload完成之后才触发的,呵呵呵。
7 楼 trydofor 2008-03-09  
思考了一下,咱不能做得过且过的营生,还是修改了import
改成:
void A9Loader.syncLoadClass(String clzz)
    sync import an js and export like java
    @param clzz (String) eg:'com.trydofor.a9text.parser.a9text'

void A9Loader.asyncLoadClass(String clzz)
    async import an js and export like java
    @param clzz (String) eg:'com.trydofor.a9text.parser.a9text'

void A9Loader.runAfterClassLoaded(Function func)
    run the func when all class imported
    @param func (Function)

我想这回能比较恰当些,看来论坛里讨论是很有积极意义的,
可惜,我发的帖子,只有福娃兄弟关注.

是我的帖子太水,还是没人关注...
学造自己的车,让别人去撞吧
6 楼 trydofor 2008-03-08  
很感谢你的回复,今天是妇女节,差点累死我 ...

曾经和jindw简单的讨论过,但是JSI的定位和a9text不一样.
因此过多的让jindw关心a9text有点不合适,而且JSI2.0在耗很多心血.

代码是程序员最好的思想交流,我读了部分JSI代码,
借鉴一些合适的内容.

本文的目的主要是做个总结,让有特别需求的人少走弯路.
同时我也非常推荐使用JSI来解决JS开发带来的麻烦.

不过a9text的确比较特别(本位主义一下),算是另类应用.

关于方法命名,我暂时就不考虑修改啦,就张冠李戴凑合着用吧.

runAfterImport的执行时机,有点特别,不同于onload.
主要是可能别多次暂停和继续,即在一个runAfterImport执行方法中,又异步载入了一个类.
这时候,下一个runAfterImport,就需要等到这个类初始化完成才执行.
而a9text中就大量使用了这样的调用.

然后,补充一点,a9loader也是要解决脚本(包)依赖关系的,在__info__.js中描述
(a9text的命名是python和java的混合体,比较乱)
之所以使用包,而不是直接释放到全局,是因为a9text里面的impl都是相同的命名.
(算是自找麻烦)
比如.
com.trydofor.a9text.render.html.a9text.A9TextRender 和
com.trydofor.a9text.render.dom.a9text.A9TextRender 就是不同的impl
所以需要使用包来隔离,这样切换impl比较方便,多个共存也容易.
这是根本原因.
5 楼 hax 2008-03-08  
i c.

你需要的是模块的动态载入(按需载入),类似于classloader。
就你的需求来说,似乎不需要命名空间管理(也就是,似乎你的import是把一个包内的名字全部导入到global上)。这较为接近我已经停止开发的老PIES的功能(除了我只用同步不用异步之外)。

假如确实如此,则你用importXXX的命名稍有误导。import通常指静态的名称导入而和模块加载并无必然联系(虽然有些语言中不是如此,但是至少java是这样)。如果只是加载,建议你把api改为A9Loader.load('...')。然后你的A9Loader.runAfterImport(function(){...})可以改成A9Loader.onload = function () {...} 跟网页编程一样了,呵呵。

JSI(以及PIES)的主要目标都包括了命名空间和名称间的依赖管理,而不是一种纯粹的加载模块管理。比如JSI处理名称(对象间)依赖或者是script文件的依赖,而不直接处理“包”(据我看,A9Loader的包实际上是一个命名的加载模块,而不是java中作为namespace的package)的依赖。

不过事实上,它们是可以提供直接处理包依赖这样的功能的,PIES的草案设计就包含了这样的设计。但是怎样设计比较合理是个费心的事情。

还有,你说“JSI的$import的特点是,载入一个js就需要callback一次”,这大概就是一个API限制,但是没有理由在原理上有这种限制(我觉得JSI原来的addScriptDepedency或许接近你的需求,除了他的单位是script file而不是你的命名过的包【模块】)。你可问问jindw现在jsi是否能满足你的需求,呵呵。
4 楼 trydofor 2008-03-07  
再写下篇总结前,做个回复,我说的运行时异步载入是这样的:
1.载入/获得一段A9text文本.
|
V
2.异步载入a9textParser和xxxRender
|
V
3.parse过程中有xxxArea --->异步载入 xxxAreaParser --->(重复2.)
|
V
4.开始xxxRender
|
V
5.render过程中发现xxxArea --->异步载入 xxxAreaRender ---> (重复4.)
|
V
6.输出render结果

其中 3.和5.就是运行时异步载入的,
无法预先得知,所以不可以提前载入.
为了提高代码可读性,就出现了a9loader的框架来解决这样的问题.

知道论坛里高手比较多,这里献丑了,希望大家提提建议和改善意见.
a9loader本身比较清晰,希望读过代码(包括JSI)的在回贴.



3 楼 hax 2008-03-05  
1. jsi好像是可以做package的。只是也可以直接做脚本依赖。
2. 没有明白你的意思。你是指它的异步载入的api不符合你的需求么?
2 楼 trydofor 2008-03-05  
首先,得声明,JSI是个不错的东西,生命力很强.
之所以说JSI不适合a9text,其根本原因有下:
1. 代码包管理,
我喜欢用java中package的概念来管理脚本.尽管有点多此一举,
但这样做是有点好处的,而这点与JSI中包的定义是不一样的.

2. 运行时异步载入.
JSI的$import的特点是,载入一个js就需要callback一次,
而a9text是运行时检测要载入的类,并全部载入后才可以执行.
如果使用JSI,基本上还需要写一个脚本管理器,并且编写代码
结构也变得复杂,难读,难维护,与其那样,不如定制一个'JSI'

3. 整体考虑.
JSI的最简版,也是要500行,a9loader算上注释也500行,而且都是自身需要的代码.
在JSI1.0的时代,a9text就有自己的loader(a9engine),处于整体的考虑,还是用
自己的最合适,不至于JSI定位扩大了,我也更正扩大

其实,不管是JSI还是a9loader,出发点和原理都是一样的,处于学习的目的,
我选择了自主,绝对没有说JSI不好的意思.

不知楼上认同否 ^_^
1 楼 hax 2008-03-05  
没有明白为什么JSI不符合你的需求。。。

相关推荐

    js等待提示,页面提交等待载入效果

    这个过程通常涉及到JavaScript编程,特别是与事件处理、动画效果和DOM操作相关的技术。 JavaScript是一种广泛使用的客户端脚本语言,它允许开发者在用户的浏览器上运行代码,从而实现交互性功能。在"js等待提示"中...

    jquery动态载入内容.zip

    2. **动态内容加载**:在jQuery中,动态加载内容通常涉及Ajax(异步JavaScript和XML)技术。使用`$.ajax()`, `$.get()`, 或 `$.post()` 方法,可以向服务器发送请求并在不刷新整个页面的情况下获取和插入新数据。 3...

    如何让动态插入的javascript脚本代码跑起来

    在JavaScript编程中,动态插入脚本是一种常见的技术,用于在页面加载后或者根据某些条件按需加载外部的JavaScript文件。这种技术在处理大型应用、优化页面性能或实现异步加载时非常有用。本文将详细介绍如何让动态...

    Ajax页面载入,等待特效

    总的来说,Ajax页面载入的等待特效是提高用户体验的重要手段,通过巧妙的设计和编程技巧,我们可以创造出各种吸引人的加载效果,使得用户在等待过程中不会感到不耐烦,从而提升整体的网站或应用的品质。

    JS树 集合 目录树 二十多个

    JavaScript(简称JS)是一种广泛用于前端开发的编程语言,它在构建交互式网页和处理数据方面扮演着重要角色。在本资源包中,你将找到二十多种不同的JS目录树实现,这些实现涵盖了各种功能和样式,可以满足不同场景下...

    IE WebBrowser编程技巧

    本WebBrowser编程技术包括Delphi、C#、VC++、VB等编程资料的集合,其中的 实例大多以Delphi为示例讲解,Delphi7 IDE开发环境。 IE_WebBrowser编程技巧 修改WebBrowser的header信息? Delphi查看...

    xml 外部载入图片

    XML(Extensible Markup Language)是一种...总结来说,XML外部载入图片涉及XML解析、URL处理、图片显示以及可能的样式和布局管理等多个步骤。通过理解这些知识点,开发者可以构建出能够灵活处理图像数据的应用程序。

    openGTS谷歌地图第三版js

    1. **载入优化**:API的载入方式有所改变,现在可以通过异步方式加载,提高了页面响应速度。 2. **简化API引用**:新的API URL简化了引用,减少了出错的可能性。 3. **移除旧版API**:谷歌逐步停止对旧版本的支持,...

    SmartClient js框架源码

    SmartClient框架采用模块化结构,这使得代码组织清晰,便于维护和按需加载。文件名称列表中的"modules"可能包含了不同功能的模块,如UI组件、数据管理、事件处理等。开发者可以根据项目需求选择加载必要的模块,...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part1.rar

     7.1.2 JavaScript和XMLHttpRequest对象   7.1.3 XML   7.1.4 一个可重用的对象   7.1.5 Ajax是正确的选择吗   7.2 为什么Ajax会破坏网站及如何解决   7.2.1 依赖JavaScript生成内容   7.2.2 ...

    基于JQuery脚本库的动态效果的设计与实现.pdf

    JQuery是一个轻量级的JavaScript函数库,能够让开发者在网页上快速简单地操作HTML文档添加动画和进行Ajax异步交互,从而提高开发者的编程效率。 在设计静态网页效果时,采用隐藏显示方法实现滑动门效果,采用计时...

    JS商品图片切换代码,来自韩国购物网站.rar

    JavaScript作为一种客户端的编程语言,能够在用户与网页交互时实时更新内容,无需刷新整个页面。 在描述中提到的"采用淡入淡出的方式变换图片",这是一种常见的动画效果,通过控制图片的透明度变化,使新旧图片之间...

    常用的页面载入提示效果特效代码

    本文将深入探讨“常用的页面载入提示效果特效代码”,介绍如何通过编程技术提升网页加载过程中的视觉体验。 一、页面载入提示的重要性 在网页加载过程中,用户可能会遇到等待时间较长的情况,此时一个富有创意且...

    ASP.NET高级编程:为校园BBS用户注册提供无刷新验证.pptx

    AJAX的核心是JavaScript对象XMLHttpRequest,该对象是一种支持异步请求的技术,用户可以使用该对象向服务器提出请求并处理响应,并且还不会影响客户端的信息通信。 ;ASP.NET3.5 和AJAX ASP.NET 3.5之前,ASP.NET自身...

    AJAX技术在Web页面开发中的应用.pdf

    它结合了JavaScript技术、XML、 DOM 等编程技术,可以使得客户端和服务器端交换数据的响应更实时,而不需要每次都重新载入整个页面。 AJAX的工作原理是将JavaScript、XML、DOM等技术组合起来,共同协作发挥各自的...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part3.rar

     7.1.2 JavaScript和XMLHttpRequest对象   7.1.3 XML   7.1.4 一个可重用的对象   7.1.5 Ajax是正确的选择吗   7.2 为什么Ajax会破坏网站及如何解决   7.2.1 依赖JavaScript生成内容   7.2.2 ...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part2.rar

     7.1.2 JavaScript和XMLHttpRequest对象   7.1.3 XML   7.1.4 一个可重用的对象   7.1.5 Ajax是正确的选择吗   7.2 为什么Ajax会破坏网站及如何解决   7.2.1 依赖JavaScript生成内容   7.2.2 ...

    13-Ajax中级.pptx

    在JavaScript中,Ajax(Asynchronous ...总的来说,理解和掌握如何创建Ajax对象、建立服务器连接、发送请求以及监控请求状态,是进行Ajax编程的基础。通过这些知识点,开发者可以构建出高效、交互性强的Web应用。

    ajax、spring、ejb试题

    Spring 提供了一个全面的编程和配置模型,对服务层的支持包括事务管理、数据访问集成等。它推崇 DI(依赖注入)和 AOP(面向切面编程),并提供了丰富的 MVC(模型-视图-控制器)框架。Spring 还支持多种持久层技术...

    仿拍拍网商品分类页面

    这个项目涉及到的主要技术是JavaScript(js)和Web前端开发,通过创建一个交互式的商品分类系统,使得用户能够方便地浏览和筛选商品。 首先,"商品分类"是电商网站的核心功能之一,它允许用户按照不同的属性(如...

Global site tag (gtag.js) - Google Analytics