当前位置: 代码迷 >> Web前端 >> promise api 与运用场景
  详细解决方案

promise api 与运用场景

热度:194   发布时间:2012-09-08 10:48:07.0
promise api 与应用场景

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/

?

?

?

?

?

?

?

?

?

?

  相关解决方案