tbad f2e 2010 review

Post on 12-Sep-2014

3.079 Views

Category:

Documents

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

淘宝广告前端2010review

TRANSCRIPT

TBAD F2E 2010 & Velocity China & D2

Review

淘宝广告事业部 李牧2010-12-20

overview• JavaScript Ninja 出品的代码和启示

• Facebook Quickling PageCache Vs. Ajaxxx

• There and Back Again : HTC(HTML Component)

• Facebook BigPipe++ : Streaming Anywhere

• 客户端无阻滞 : 第三方广告代码的实践

• 服务端无阻滞 :CommonJS NodeJS CFO 体系 Web 死后 jser 的未来

• JavaScript 包管理 + 模块化 : YUI3 & Kissy Vs. KissyLite

• Google Clousure Compiler 启示 : KissyLite 预编译时间窗口优化性能

• Jscex 和 kslite 对异步编码的简化

JAVASCRIPT NINJA 出品的代码和启示

Topic 1:

DomReadyFirefox Chrome Safari Opera:

DOMContentLoaded

IE:

doScroll or script defer

onreadystatechange for iframe

<script> onloadDom 载入的 JS 文件载入完成且执行完成的事件

IE Opera:

onreadyStateChange

Firefox Chrome Safari Opera:

onload

insertAdjacentHTML

IE Chrome Safari Opera:

insertAdjacentHTML

Firefox:

HTMLElement.prototype.insertAdjacentElement = function(where, parsedNode) { };

HTMLElement.prototype.insertAdjacentHTML = function(where, htmlStr) { };

iframedJS父页面升级 document.domain,IE 下IframedJS 解决方案 :

<iframe id= src= "javascript:void(( function(){var d=document;d.open(); d.domain='a.com';d.write('');d.close()})())" ></iframe>

BugFix@CKEditor

Range : insertNode

Firefox Chrome Safari Opera:

insertNode

IE:

圆心的实现

http://www.planabc.net/2010/11/26/range_insertnode/

Ninja 的代码和启示不同浏览器 , 使用不同途径实现相同功能 .

对 JavaScript 或 Dom 的功能进行补强 .

解决实际开发中遇到的重大困扰 !

-- 了解更多的浏览器特性 , 包括那些某种浏览器独特的特性以拓展解决问题思路 , 因为特性都是为解决实际问题而加入的 .

FACEBOOK QUICKLING PAGECACHE VS. AJAXXX

Topic 2:

网站性能优化的目的

运行流畅 加载迅速

Ajaxxx架构来自于系统特点 .

1. 页面不多 ,<100 个

2. 多数页面重复 , 由组件搭建

3. 页面有数据的区块不多

4. 不需要 SEO

Ajaxxx加载迅速

1. 所有静态资源在 CDN 上

2. 通过 Ajax 只加载需要的数据

3. 没有任何静态资源加载 2 次以上

展现流畅

1. 没有 load,unload 消耗

2. 没有重复渲染

3. 基于事件绑定的组件框架

同类的 Facebook Quickling

Quickling vs Ajaxxx

• Link Controller – FB 使用事件代理 , 我们使用的是原生的link

•HistoryManager -- 基本一致

• Bootloader -- 我们有面向开发环境的优化

• Busy Indicator

•CSS Unloading

•Resetting timer functions

• Permanent link

内存问题Facebook 会在 10 个页面之后强制刷新

我们不能这样做 , 因为 IE6 强制刷新丢失存在于 iframe 的历史

我们解决问题的两个方向

1. 将历史存入 cookie 或其他本地存储模式 , 强制刷新能够恢复历史 , 配合页面间内存泄露预防

2. 减少 YUI3 依赖 , 解决页面内内存泄露问题

PageCache

PageCache 启示我们动态数据及时性要求高 , 动态数据少 , 所以不缓存动态数据 .

Facebook 缓存动态数据遇到的非常棘手问题我们都没有 .

Incremental updates

In-page writes

Cross-page writes

如果我们系统预知到了这些问题 , 我们不会这样架构 .

但从 Facebook, 我们看到的是解决问题的智慧 , 勇气和信心 !

同类的 New Twitter

MUSTACHE 模板系统 支持 NodeJS

Ajaxxx 2011优化内存使用

更换模板系统为 MUSTACHE

使用 NodeJS, 让页面可以在服务端生成

页面组件更加 HTC

THERE AND BACK AGAIN : HTC (HTML COMPONENT)

Topic 3:

浏览器内置组件的构成原生的 select 组件 我们开发的 select 组件

按照浏览器构建内置组件的方式构建自定义组件

Microsoft HTCIntroduced in Microsoft® Internet Explorer 5, HTML Components (HTCs) provide a mechanism to implement components in script as Dynamic HTML (DHTML) behaviors.

HTC 基本架构为自定义组件开发 , 各自的属性 , 事件和方法 .

容器 : 通过样式中的 behavior 关联至指定容器对象 .

属性 : 通过标签的自定义属性初始化 , 也可以通过 new方法传入的属性初始化方法 : 开发暴露给使用者的自定义方法事件 : 直接在标签上订阅事件 , 或通过脚本注册事件监听事件产生 : 一般通过事件代理 , 监听容器内原生键鼠事件 ,根据触发事件的元素和事件类型 , 决定是否触发自定义事件 . 也可以不采用代理的方式直接注册组件内子对象的事件监听 ,处理较复杂的情况 ( 不冒泡的事件 ).

Youtube UIX Widget

Youtube UIX Widget

我们的实践 X-HTC基于 YUI3 和 HTC 组件构建思想 , 开发 X-HTC 前端组件架构

•继承 YUI3 的 Base 使用 YUI3 的 ATTR管理属性

• 使用 <ins> 标签关联组件与容器

• 使用 mixin 的方式区分私有方法集 ,公共方法集与事件代理方法集

• 组件对象即为 YUI3 的 EventTarget 实例 ,提供自定义事件支持

•扩展 YUI3 Widget 对组件生命周期的管理 .(initializer, renderUI, bindUI, syncUI, renderData, bindData, destructor)

•扩展模块属性 , 解决 HTC 对其他模块的依赖 .

•提取数据源 , 以及数据结构对象 ,每个组件为单一数据结构(List,Tree,Set,Hash) 服务 , 从多数据源获取数据 .

X-HTC 解析

组件名称属性对象代理事件自定义事件公共方法依赖模块

X-HTC 解析组件解构层次

公共方法集mixin事件代理集mixin

组件数据绑定

数据结构层次

X-HTC 未来减少对 YUI3 的依赖 , 更好的控制内存

使用 mustache 模板系统渲染组件

适应 NodeJS 服务端组件生成

FACEBOOK BIGPIPE++ : STREAMING HTMLSTREAMING AJAXSTREAMING CROSSDOMAIN FRAMES

Topic 4:

何时使用 Bigpipe

当页面第一个请求耗时很短时 , 完全没有必要使用 Bigpipe

Facebook 由于高度定制化 ,首个请求服务端生成 HTML 耗时 2s

以上

BigPipe技术要点一 .Chunked HTTP:

一个 HTTP请求可以分段发给发给客户端 .

PHP 中 , 通过 flush(),输出响应片段

二 . 浏览器支持分段解析 HTML:chunk1:

<body><div>先解析先渲染 </div>

chunk2:<div> 后渲染 </div>

</body>

BigPipe 实质 : Streaming

ChunkedHTTP: 让数据分段流动 , 成为一切Streaming 类解决方案的基础 .浏览器分段解析 : 让 HTML,JS 数据拥有被分段解析的可能Facebook BigPipe

chunk1:<body>

<div id=‘pagelete1’/><div id=‘pagelete2’/>

<script>//pagelet2</script>chunk2:

<script>//pagelet1</script></body>

Streaming++

Streaming Ajax:使用 iframe 做 Ajax请求 ,即可做到将异

步动态数据逐步流入 .这也是长链接 (comet) 的一种实现方式 .

Streaming++

Streaming Cross Crossdomain iframe:

使用一个 iframe 做 Streaming,利用Dom 方法将数据填写到页面其他 iframe 中 .第三方内容依然可以从 Streaming受益

a.com b.com:streaming

iframe

b.com: blank1

b.com: blank2

chunk1

chunk2

客户端无阻滞 : 第三方广告代码稳定性和性能优化

Topic 5:

广告影响网页稳定性<script> alimama_pid="mm_1_2_3";alimama_type=2; alimama_width=270;alimama_height=390; </script> <script src="http://a.alimama.cn/inf.js"></script>

<iframe(script) src="http://t.alimama.com/a?i=mm_1_1_1&fv=10.1&rd=xyz&u=a.com%2Fa.html"></iframe(script)>

inf.js

document.write:

静态脚本阻滞是根源脚本阻滞 :HTML 中 <script>节点对应的脚本下载且执行结束之前 , 浏览器不会发起任何新的HTTP请求 , 也不会对该节点以下的任何内容进行渲染 .

Script Dom Element

使用 ScriptDomElement 解决脚本阻滞问题

function scriptDomElement(u) { var s = document.createElement('script'),h = document.getElementsByTagName('head')

[0];s.src = u; s.async = true;if(h)h.insertBefore(s,h.firstChild);

}

通过 Dom 方法创建一个 script节点 ,并插入到文档当中 .在各种浏览器中这种方式都能保证脚本与其他资源并行下载 .

天生稳定的广告埋点<script>

document.write('<a style="display:none !important" id="t-a-{id}"></a>');

t_h = document.getElementsByTagName('head')[0];

t_s = document.createElement('script');

t_s.async = true;

t_s.src = 'http://{host}/{path}?i={pid}';

if(t_h)t_h.insertBefore(t_s,t_h.firstChild);

</script>

输出占位锚点做位置参照 <a style="display:none !important" id="t-a-{id}"></a>

异步无阻加载广告数据后 ,回调函数将广告内容插入到锚点之前 .

老埋点提速改造<script>

alimama_pid="mm_1_2_3";alimama_type=2;

alimama_width=270;alimama_height=390;

</script>

<script src="http://a.alimama.cn/inf.js"></script>

inf.js-3.0<script>

alimama_pid="mm_1_2_3";alimama_type=2;

alimama_width=270;alimama_height=390;

</script>

<script src="http://anydomain/inf.js"></script>

inf.js-3.0<script src="http://anydomain/inf.js"></script>

<script>

alimama_pid="mm_1_2_3";alimama_type=2;

alimama_width=270;alimama_height=390;

window.alimama_show && alimama_show();

</script>

inf.js-3.0<!-- http://anydomain/any.js include the content of inf.js -->

<script src="http://anydomain/any.js"></script>

<script>

alimama_pid="mm_1_2_3";alimama_type=2;

alimama_width=270;alimama_height=390;

window.alimama_show && alimama_show();

</script>

inf.js-3.0<script>

//content of inf.js

</script>

<script>

alimama_pid="mm_1_2_3";alimama_type=2;

alimama_width=270;alimama_height=390;

window.alimama_show && alimama_show();

</script>

http://a.com/a.html:

alimama_show()

<script src="inf.js"></script><script> alimama_show();</script>

<iframe style="display:none !important" id="anchor-pid"> <!-- ad content--></iframe>

<head> <script src="main.js"></script></head>

<div> <!-- ad content--></div>

同步

异步回调

异步回调

异步

服务端无阻滞 : COMMONJS NODEJS CFO(CLOSURES+FUNCTIONS+OBJECTS)体系 WEB 死后 JSER 的未来

Topic 6:

severside

clientside

服务端阻滞引擎前端机 php 使用 kfc 从其他后台服务获取数据

kfc_sendmsg($pg, $msg)

//阻滞 ..线程等待数据返回…

$ret = kfc_recvmsg($pg, KFC_SYNC, $timeout);

更通俗的例子var result = db.query("select..");// use resulteither blocks the entire process orimplies multiple execution stacks.

db.query("select..", function (result) {// use result

});allows the program to return to theevent loop immediately.

NodeJS

node.js : 基于事件驱动的服务端JavaScript

优势在于同时处理大量不同类型的 I/O

通过让所有网络系统 I/O无阻塞 , 让所有文件系统 I/O异步化来达到这个目标

NodeJSNode's goal is to provide an easy way to build scalable network programs. many client connections can be handled concurrently.

Node tells the operating system (throughepoll, kqueue, /dev/poll, or select) that it should be notified when a new connection is made, and then it goes to sleep. If someone new connects, then it executes the callback. Each connection is only a small heap allocation.

NodeJS 性能同类比较

100byte响应大小并发与 RT 关系 300并发响应体大小与 RT关系

nginx v0.7.65 thin v1.2.7 (ruby 1.9.1-p376)node v0.1.91 tornado v0.2 (python 2.6.4)

TCP By NodeJSvar net = require('net'),srv =

net.createServer(),socket = null;

var onDataArrived = function(data){

socket.write(data);

};

var onConnectSuccess = function(skt){

socket = skt;

socket.addListener("data",onDataArrived);

};

srv. addListener("connection",onConnectSuccess);

srv.listen(8124, "127.0.0.1");

var net = require('net');

net.createServer(

function (socket) {

socket.addListener("data",

function (data) {

socket.write(data);

}

);

}

).listen(8124, "127.0.0.1");

Add Some Sugar

匿名函数函数做参数作用域链链式调用

Why JavaScript ?将服务端基于阻塞的系统改造为事件驱动系统 ,而 GUI 系统 ( 如浏览器 ) 多是事件驱动的系统 .JavaScript 是面向事件驱动系统成熟高效的语言 .

无需为页面上每个可点击的部件安排一个线程等待点击的发生 .

事件驱动中的状态保持function main(){

var name = "limu";

var age = db.query("select age from person where

name="+name);

print("the age of" + name + "is" + age);

}

print("query start");

main();

print 时变量 name 和 age 同时可用 .

事件驱动中的状态保持function main(){

var name = "limu";

db.query("select age from person where

name="+name,

function(age){

print("the age of" + name + "is" + age);

}

);

}

main();

print("query start");

假设查询耗时 3秒 ,3秒后执行回调函数 .print 时 age

可用 .

而一般而言 name作为 main函数的局部变量已经出了其作用域范围而被销毁 .

如果想继续用 name变量需要额外的保存动作 ,即状态保持 .

CFO 体系

Understanding this strong relationship between objects, functions, and closures will improve your JavaScript programming ability giving you a strong foundation for any type of application development.

基于闭包的状态保持function (socket) {

socket.addListener("data",

function (data) {

//10s 之后 data 到达本函数运行// 为什么可以访问 socket

socket.write(data);

}

);

}

闭包 :function 在生成时会保存所有当时可访问变量的引用 , 以备函数运行时使用 .

CommonJS:JS想成为服务端语言还缺什

么• Modules

• Binary strings and buffers

• Charset encodings

• Binary, buffered, and textual input and output (io)

streams

• System process arguments, environment, and

streams

• File system interface

• Socket streams

• Unit test assertions, running, and reporting

• Web server gateway interface, JSGI

• Local and remote packages and package

management

CommonJS 是一种规范, NodeJS 是这种规范的部分实现之一。

Web死后 Jser 的未来

由强大的 CFO体系支撑 :熟练的面向事件驱动系统开发能力无阻塞思想和熟练的异步回调式编码能力熟练的面向对象程序设计能力

我们的动作•为浏览器端 JS 实现模块化和包管理以及相

关的性能优化

•做异步编程的简化和性能优化

•在服务端使用 NodeJS 渲染生成页面的技术 ,结合 Ajaxxx, 在不支持 JS 的浏览器中也能够正常使用 Ajaxxx 构建的系统 . 做到一次编码 ,渐进增强 .

JAVASCRIPT 包管理 + 模块化 :YUI3 & KISSY VS.KISSSYLITE

Topic 7:

PyPI

第三方广告代码要求

•必须稳定

•足够小

•结构化

•无限可扩展

kissyLite

kissylite, 是 kissy 的一个支持有限方法的子集

目标是用 1.5k 代码支持可扩展的包管理和模块化管理

预览地址

ksLite -- 足够小 统一风格的 OOP,异步的带依赖关系模块化 ,简单的模板 .

• S.mix

• S.extend

• S.clone

• S.add

• S.use

• S.getScript

• S.substitute

ksLite -- 模块化 模块声明S.add(modName,attachFunction,Config);在 attachFunction 中做类的声明 , 在 Config 中指定当前模块所依赖的其他模块 .

模块使用S.use(modNames,callbackFunction);可以一次使用多个模块 , 使用时按需载入所需模块 , 在 callbackFunction 中即可使用已加载模块中声明的类来生成实例 .

KsLite Vs.YUI3 Kissy

YUI3 和 Kissy 同样提供模块化 ,但所有模块在 use 之前必须 add.

这种模式不满足第三方代码无限可扩展需求 .

KsLite引入包管理 ,提高扩展性 .

ksLite -- 基于包的扩展 包内无限可扩展 => 模块名由包名 , 路径 , 文件名 .三部分构成 .

{packagename} - [ {path_0} - ... - {path_n} - ] {filename}

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

ksLite -- 基于包的扩展 可扩展无限包 => package root router

在一个地址记录所有可用的包以及对应的 class root.

S.Config.lt_pkgrouter = http://a.alimama.cn/kslite/router.js

S.mix(S.Config.lt_pkgs,{

pkg1:"http://a.alimama.cn/pkg1/",

pkg2:"http://demo.taobao.com/tbad/pkg2/"

});

当自带 S.Config.lt_pkgs 没有相关配置时询问 pkgrouter.

ksLite -- 命名约定 S.add("pkg1-path1-mod1",function(S,P){

S["pkg1"] = S["pkg1"] || {};

P = S["pkg1"];

});

S.use("pkg1-path1-mod1",function(S,P){});

保证包内对象都在名称空间 P,即 S.P 内 .

相当于另一个途径实现 S.app(),嵌入至 S 的 app.

为了被 Kissy兼容 ,P 只能作为开发约定 , 手动写在每个包中 .

ksLite -- 轻量的 add S.add = function(name, fn, config){

var mods = S.Env.mods, mod;

if (mods[name] && mods[name].status > INIT)return;

mod = {name: name,fn: fn || null,status: LOADED};

mods[name] = S.mix(mod,config);

}

不提前 attach,保证模块在使用之前没有多余的代码执行消耗 .

可选优化 :domready 之前按需执行 ,domready 之后选择性预热 .

ksLite -- 简单的 use S.use = function(modNames, callback){

var mods = S.Env.mods;

modNames = modNames.split(',');

S.attachMods(modNames, function(){

if (callback) callback(S);

});

}

将 attachMods单独提出来 . 不止供 use 中使用 .

ksLite – 明确的attachMod

如果模块 LOADED, 直接 attach.

如果模块没有 LOADED,则异步载入模块 .然后 attach.

模块 load 之后 ,attach 时如果发现 requires.

attachMods(requires,callbcak). 之后 attach.

multiAsync 加载多个模块

S.attachMods = function(modNames,callback){ var i, asyncers = {}; for (i = 0; i < modNames.length; i++) { asyncers[modNames[i]] = { f: S.attachMod, a: modNames[i] }; } S.multiAsync(asyncers, callback);

}

避免循环引用模块和包都是无限可扩展的 , 一旦出现循环引用 ,影响客户页面稳定性

场景 :

mod-a requires mod-b

mod-b requires mod-c

mod-c requires mod-a

运行时 :

S.use("mod-a",function(){});

throw new Error("Fatal Error,Loop Reqs!");

简单粗暴的算法在 env 中有一个对象记录

x 模块依赖哪些模块

x 模块支持哪些模块

当出现 x 依赖 x 的时候 thorw error.

ksLite 的相关问题避免循环引用解决了 ksLite 可能带来的稳定性隐患

遗留问题 :

串行模块加载的性能问题

attach( 模块定义 ) 何时运行的矛盾 ,提早运行延缓页面初始加载和完全按需运行拖慢事件响应 .

异步化编程编码方式的简化

GOOGLE CLOSURE COMPILER 启示 : KISSYLITE 在预编译时间窗口优化性能

Topic 8:

D2:Closure Complier

在 D2论坛 , 来自 Google 的 Hedger介绍了 <<Coding Better Object-Oriented JavaScript with Closure Compiler>>

Google Closure Complier 告诉我们可以在代码发布前增加一个预编译步骤 , 在此时除了最小化压缩代码之外 ,编译器配合编码时的一些标准注释提示 , 来统一 OO风格 , 减小对象深度以提高访问速度 , 使用枚举 , 常量等等其他语言好用的特性 .

关于预编译相对于编译型语言 ,JavaScript缺少了编译这个环节 . 传统编译器把代码转换为可执行的机器指令的动作交由浏览器中的 JS引擎在运行时执行 .

但现代的编译器除了代码翻译还有哪些功能 ? 而 JS引擎能在运行时 Cover住这些任务么 ?

最常见的运行时编译无法解决的问题就是代码压缩 . 所以我们有各种 Compressor 让代码传输给浏览器的时是最小的 . 

Google Closure Complier 解决了另外一些问题 .

预编译打开一扇窗Google Closure Complier 更有意义的是告诉我们 , 可以有这样一个发布前预编译的步骤 , 可以有这样的一个时间窗口 , 在这个时候结合我们自己的应用 ,结合我们自己遇到的问题是不是也可以做点什么 .

我们在预编译时间窗口解决 ksLite遗留的性能相关问题 .

颗粒化的性能问题模块开发者开发一个功能 , 将它封装在 mod-a 中 . 然后我们发现 mod-a 中可以抽象出来 mod-b于是就有了 mod-b, 同时 mod-a requires mod-b.

模块使用者根据接口约定 S.use("mod-a“,function(S){});

拆分前mod-a.js

拆分后mod-a.js

mod-b.js

问题 :增加一个请求 , 而且是串行加载 .是否要为可能的重用而进行会引入性能问题的拆分 ?

预编译时优化模块开发者不用考虑性能问题 , 进行最合适的颗粒化 .

模块使用者在开发期间始终按照接口编码 ,即 S.use("mod-a");

编译器建议在发布之前 , 模块开发者颗粒已确定 , 模块使用者功能开发完毕 ,编译时建议此处应该 S.use(“mod-a,mod-b”); 以便并发加载

编译后mod-a.js

mod-b.js

解决了串行的问题 .

编译前mod-a.js

mod-b.js

打包策略mod-b 可能在 mod-a 之前使用也可能跟随mod-a引入 .

如果多数情况mod-b 在 mod-a 之前 , 那拆分带来好处 .

如果多数情况mod-b跟随mod-a引入 , 那 mod-b 的内容合并至 mod-a 将会带来好处 .应该合并 a,b.

mod-a.js (include mod-b.js)

不应该合并 a,b.

mod-b.js

mod-a.js

最佳打包实践预编译结合自动化测试可以构建最适合当前应用的打包方案 .

预编译结合线上使用数据反馈 , 可以构建最优打包方案 .

Facebook 在 Velocity介绍的 << 静态资源管理和优化>>,结合 Facebook 实际数据统计 ,计算出最优的模块合并方案 .

预加载与延迟加载的矛盾模块 add 时要不要 attach( 执行类定义相关代码 ).

即模块 add 时运行类定义还是 use 时运行类定义 .

add 时 attach: 会导致页面加载过程中不必要的代码运行消耗 ,拖慢页面展现速度 .

use 时 attach: 会导致事件触发时 , 由于需要得到模块attach 以及可能的依赖模块加载 ,导致交互事件响应缓慢 .

按需执行 +选择性预热

add 时不 attach. 优先保证页面展现速度 .

在 DomReady 之前 , 页面展现阶段 , 只执行需要的代码 .

在 DomReady 之后 , 对页面的交互功能进行预热 .

页面上有很多功能 , 应该提前预热哪些 ?

结合重点 Case 自动化测试用例 , 预编译可以给出最优的预热方案 .

S.ready(function(){S.use("mod-b,mod-d,mod-e")});

JSCEX 和 KSLITE 对异步编码的简化Topic 9:

asyncer -- 异步执行单元/*

* @interface asyncer 可能需要等待再回调的 function.

* @param { * } args

* @param { Function | Object } callback info

* @param {number} timeout(ms)

* @return {Object}

*/

function ayncer(args , callback,timeout){ }

parallel asyncers asyncerA(a,function(resA){ window.resA = resA; if(window.resB)c();});

asyncerB(b,function(resB){ window.resB = resB; if(window.resA)c();})

function c(){ //your code run after resA & resB both returend. }

serial asyncers asyncerA(a,function(resA){

asyncerB(b,function(resB){

asyncerC(c,function(resC){

//your code.

})

});

});

S.multiAsync S.multiAsync(asyncers,callback,timeout);

面向 asyncer 的 interface, 通过简单的开发 ,避免parallea synce 类操作等待其他操作完成时的hardcode.

将开发 S.serialAsync,避免过多回调造成的作用域链过长而导致的性能下降 .

更先进的异步编程简化Jscex(JavaScript Computation Expressions) 由老赵开发 , 在 D2作品秀环节介绍给大家 .

Jscex 让大家以阻塞的模式写代码再经过 Jscex 实时编译器将代码转化为异步的模式执行 .

更先进的异步编程简化前面的代码编译为下面这段 ,交给浏览器执行 :

如果说异步式编程像机器语言一样难写难懂 ,Jscex 将其转化为高级语言一样易于编写和阅读 . 而 ksLite提供的 multiAsync和 serialAsync则是像汇编语言一样用较少的代码代价对异步编程略微简化 ,避免一些 hardcode, 同时解决一些不易处理的性能问题 .

Thanks!limu@taobao.com

http://twitter.com/lenel_li

top related