promise 是 commonjs 社区中提出的异步规范,其简洁直观的 api 使得异步读值操作更易于理解和使用,主要 api 包括:
?
API
?
Defer
?
功能实现者调用 Defer() 后产生 Defer 对象,它包括 promise 属性以及 resolve 和 reject 方法
?
promise 对象
?
功能调用者通过调用 promise 的 then 方法添加成功回调和失败回调函数。多次调用 then 添加的回调函数最终“并行”执行,互相独立。
?
resolve/reject
?
功能实现者通过 resolve/reject 来通知 promise 对象成功与否并传递指定的参数给调用者的回调函数来执行。
?
note:
?
通过分离 Defer 对象和 promise 对象,可以达到功能实现者和调用者的权限分离,符合 Object-capability-model?从而更有利于系统的安全。
?
all
?
通过 all 方法生成一个新的 promise 对象,通过该对象可以监控一批 promise 对象,只有当全部 promise 都成功时才使得新的 promise 对象成功,否则只要有一个 promise 对象失败那么新生成的 promise 就算做失败。
?
when
?
调用 when 可以统一获取 promise 对象和非 promise 对应的值,屏蔽异步的差异。
?
api 使用
?
then
?
1. 统一的回调注册
?
then 方法提供了一个统一的回调注册接口,无论注册时该异步 promise 是否已经成功,都会保证回调函数会被及时调用。
?
例如:
?
可以成功前注册:
?
?
var defer= S.Defer(); defer.promise.then(function(v){ alert(v===1); }); setTimeout(function(){ defer.resolve(1); },5000);?
也可以在成功后注册(仍然会被调用)
?
?
var defer= S.Defer(); defer.resolve(1); setTimeout(function(){ defer.promise.then(function(v){ alert(v===1); }); },5000);?
2. 链式操作
?
then 会返回一个新的 promise 对象,那么在这个返回对象上可以继续调用 then 方法,而参数值则是上一个 then 方法的返回值:
?
?
var defer = S.Defer(); defer.promise.then(function(v){ alert(v===1); return v+1; }).then(function(v2){ alert(v2===2); }); defer.resolve(1);?
3. 嵌套链式操作
?
更进一步:回调函数也可以返回一个 promise 对象,那么 then 返回的 promise 对象则会等待回调函数返回的 promise 对象成功后才算成功,并且最后一个 then 的回调函数的参数为 导致前一个 then 回调函数返回的 promise 对象成功 的值:
?
?
var defer = S.Defer(); defer.promise.then(function(v){ alert(v===1); var d2= S.Defer(); setTimeout(function(){ d2.resolve(2); },1000); return d2.promise; }).then(function(v2){ alert(v2===2); }); defer.resolve(1);?
all
?
使用 all 也可以达到嵌套调用的效果(同时等待多个 promise 成功),并可一次性得到导致所有 promise 成功的值:
?
?
var defer = S.Defer(); var defer2 = S.Defer(); setTimeout(function(){ defer2.resolve(2); defer.resolve(1); },1000); S.Promise.all([defer.promise,defer2.promise]).then(function(vs){ alert(vs[0]===1); alert(vs[1]===2); });
?
?
when
?
使用 when 可以不加区别得对待 promise 对象和非 promise 对象,通过成功回调可以一致得获取最终结果:
?
function check(p){ S.Promise.when(p,function(v){ alert(v===1); }); } var defer=S.Defer(); defer.resolve(1); check(1); // => alert(true) check(defer.promise); //=> alert(true);?
?
使用场景
?
domReady?
?
domReady 是个异步过程,具备以下特征使得它非常适合使用 promise 来实现:
?
1. domReady 添加回调时可能该事件已经触发过。
?
2. 多个 domReady 添加的回调并不需要前后依赖,并且要求其中一个回调失败并不影响其他回调(即回调间独立)
?
那么内部实现即可将 S.ready(fn) 的调用转交给内部的 readyDefer.promise.then。那么当浏览器 domready 时只需简单调用 readyDefer.resolve(S) 即可.
?
io/ajax
?
io/ajax 一般也是异步 io,通过 promise 实现 io,那么就可以摆脱必须将处理逻辑统统写在一处的限制:
?
?
var r=S.io({...}); r.then(function(v){ // logic 1 }); r.then(function(v){ // logic 2 });
?
并且通过嵌套以及 all 也可以很容易支持多个系统间的相互时序依赖。
?
串行:
?
?
var r=S.io({..}); r.then(function(v){ return S.io({..,data:{v2:v+1}}) }).then(function(v2){ // logic v2 })?
并行:
?
?
S.Promise.all([S.io({url:'u1'}),S.io({url:'u2'})]).then(function(vs){ alert("u1+u2 => " + (vs[0]+vs[1])); });?
Module Loader
?
同 io 类似通过用嵌套以及 all 来管理多个 module 代码文件的串行以及并行加载,可以更加清晰得组织代码结构。
?
?
Refer:
?
KISSY.Defer API & KISSY.Promise API
?
http://wiki.commonjs.org/wiki/Promises
?
http://en.wikipedia.org/wiki/Futures_and_promises#Read-only_views
?
http://en.wikipedia.org/wiki/Object-capability_model
?
https://github.com/kriskowal/q
?
http://www.sitepen.com/blog/2010/05/03/robust-promises-with-dojo-deferred-1-5/
?
http://dojotoolkit.org/documentation/tutorials/1.6/deferreds/
?
http://api.jquery.com/category/deferred-object/
?
?
?
?
?
?
?
?
?
?