$.when用于监听多个 Deferred对象resolve,reject,notify的一个东西,今天我们就来看看它是怎么玩的。

基本使用

我们先来看一个最简单的demo:

我们定义了两个Deferred对象,然后用$.when等待他们同时完成,我们发现当两个Deferred对象都完成的时候,$.when的done也被执行了,那么这背后的原理是什么呢?

background Layer 1 var d1=$.Deferred(),d2=$.Deferred(); resolve队列 reject队列 progress队列 state=resolved reject队列disable progress队列lock resolve队列disable progress队列lock state=rejected resolve reject notify f1 d1 d1.done(f1).fail(f2).progress(f3); resolve队列 reject队列 progress队列 state=resolved reject队列disable progress队列lock resolve队列disable progress队列lock state=rejected resolve reject notify f4 d2 resolve队列 reject队列 progress队列 state=resolved reject队列disable progress队列lock resolve队列disable progress队列lock state=rejected resolve reject notify f7 $.when f5 d2.done(f4).fail(f5).progress(f6); $.when(d1,d2).done(f7).fail(f8).progress(f9); f1 f3 f6 f8 f9 checkIsFulll 调用reject 调用notify checkIsFulll 调用reject 调用notify checkIsFulll:当个数满足的时候,调用$.when的resolve 调用reject:调用$.when里面的reject 调用notify:调用$.when里面的notify

首先当有两个或两个以上的Deferred对象的时候,$,when会额外创建一个Deferred对象用来监听他们的动作。

$.when会在每个Deferred对象里的resolve队列,reject队列,progress队列里面添加一个方法:

resolve队列:如果个数满足,调用$.when的resolve。

reject队列:直接调用$.when的reject。

progress队列:直接调用$.when的notify。

$.when里面含有非Deferred对象

当$.when里面含有非Deferred对象的时候,是不会计算他们的,例如有5个参数,三个不是Deferred对象,那么会额外创建一个Deferred对象去监视其中的两个Deferred对象,就和上面的情况一样了。

那么假如可怜到一个都不是Deferred对象怎么办呢?那么这个时候$.when还是会创建一个Deferred对象,只不过$.when发现没有Deferred对象,立马执行了resolve而已。

$.when里面有且只有一个Deferred参数

当$.when里面有且只有一个参数的时候,是不会额外创建一个Deferred对象的,这个时候所有的done,fail,progress都是挂在那个Deferred对象上的。

background Layer 1 var d1=$.Deferred(); resolve队列 reject队列 progress队列 state=resolved reject队列disable progress队列lock resolve队列disable progress队列lock state=rejected resolve reject notify f1 d1 d1.done(f1).fail(f2).progress(f3); $.when(d1).done(f4).fail(f5).progress(f6); f1 f3 f5 f6 f4

源码如下:

源码里先是判断是否有唯一的Deferred,如果是,那么就不创建新的Deferred了,否则就创建一个。

然后给每个Deferred里面的三个队列分别注入一个方法,然他们和$.when创建的Deferred对象关联。

当然如果一个Deferred对象都没有,那么就直接resolve了。

最后

常见的$.ajax返回的就是Deferred的promise,因此常见的用法是$.when($.ajax(/**/),$.get(/**/)).done(){}。

其他文章

0
我要评论

评论

返回
×

我要评论

回复:

昵称:(昵称不超过20个字)

图片:

提交
还可以输入500个字