JQuery 的 deferred . promise对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JQuery 的 deferred . promise对象相关的知识,希望对你有一定的参考价值。

描述: 返回一个 Promise 对象,用来观察当某种类型的所有行动绑定到集合,排队与否还是已经完成。

这句话是什么意思看不懂呀 -_-!!

谁来帮忙解释下

返回一个 Promise 对象,用来观察当某种类型的所有行动绑定到集合,排队与否还是已经完成。

用来观察当某种类型的所有行动绑定到集合,排队与否还是已经完成。
是什么意思

用来观察 XX 与否还是已经完成 这个明白,但是XX的地方不明白

啥是 所有行动绑定到集合,排队 ?

  你说的这段描述是对 jQuery(selector).promise()的描述,并不是 jQuery.Deferred() 的描述。

  原文是:

Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished.

  而这段话是说:

jQuery(selector).promise() 函数是返回一个 Promise 对象,这个对象的作用是当绑定到集合【也就是$('div')这样取到的集合】的指定类型的所有动作(promise方法的第一个参数 type ,默认是fx,也就是动画)是否已经完成了。


  英文水平有限,有些地方看不怎么懂,这话说得有点乱,不过意思应该是这样的,举个例子:

$('#message')
.animate(width:400, height:240, 3000)
.promise()
.done(function()
    console.log('animate end');
);

  也可以写成:

$('#message').animate(width:400, height:240, 3000);

var promise = $('#message').promise();

promise.done(function()
    console.log('animate end');
);


  这里的 $('#message') 就是所说的collection,


  而动画 animate (即 fx)就是 certain type,


  里面的所有动作就是 action queue,当然,这里只有1个,就是默认的fx (但是文档中没有找到介绍其它的类型)。


  后面的 var promise = xxx 就是指返回的 Promise对象,这个对象在收到animate 方法里面的信号(这个信号包括 resolve, reject, notify, resolveWith, rejectWith, and notifyWith等)可以调用方法done(当然还有不少其它的方法,这里没用到就不说了,自己看文档吧),然后执行done的回调函数了。


  animate方法会自己发送promise的信号,不用手动去处理。具体细节可以参考 jQuery.Deferred() 方法,在API的介绍中有这个方法的使用示例。


  需要注意的是, jQuery(selector).promise()和jQuery.Deferred().promise()是不一样的。

  从目前我知道的来说,jQuery(selector).promise() 是专门用来处理jquery中的动画(animate)使用的,而jQuery.Deferred().promise()使用的范围更广,没看源码,不过猜一下,我觉得 jQuery(selector).promise()是jQuery在动画的时候对jQuery.Deferred().promise()的特殊实现(或者叫做功能封装)。


  然后再说一下jQuery.Deferred().promise()吧。它的一般用法为:

var defer= $.Deferred();
$.when(defer.promise()).then<done|fail|....>(参数...)

defer.resolve('传参数或留空');
defer.reject('传参数或留空');
defer.notify('传参数或留空');
// ..... 其它信号

实例请自己去看API页面。


上面的defer是一个延迟对象(deferred)引用,表示这个对象的信号会在将来发出。

接下来的 $.when(defer.promise()) 是指jQuery 要监视 defer的信号,收到信号后执行后面的then(或者done, fail或其它)的函数。而后面的defer.resolve<reject|notify>则是发出信号,通知jQuery延迟调用已经执行了,jQuery收到信号后,就去调用这个延迟的promise()后面的函数。

参考技术A allenm

Published
2012 年 01 月 01 日

in javascript
jQuery deferred 对象的 promise 方法
jQuery 从 1.5 版本引入了 deferred 对象,这是一个基于 CommonJS Promises/A 的设计,为了方便异步操作,大家都知道,在 js 中,异步代码是非常的多。
这篇博客不是来详细讲解 $.Dererred 的,阮一峰 的博客里有一篇博客详细介绍了这个。但是在这篇博客中,关于 promise() 这个方法的讲解却是错误的,我发现这个是因为我徒弟去学习这个的时候,看了这篇文章,然后我让他给我讲述的时候,发现了这个错误。所以我想写篇 blog 来说明下。
update(2012.1.2): 我针对此问题给一峰发了 email, 他已经针对下面的问题进行了更新,下面的引用来自他最初的版本。现在他博客中对 promise() 的讲解是正确的,如果想了解整个 Deferred 对象,建议直接移步他的博客中学习。同时感谢阮一峰发现的我这篇博客中的一个小错误,最后面的那段代码,现在已经修复。
下面是引用自阮一峰的博客:
这里有两个地方需要注意。
首先,最后一行不能直接返回dtd,必须返回dtd.promise()。原因是jQuery规定,任意一个deferred对象有三种执行状态—-未完成,已完成和已失败。如果直接返回dtd,$.when()的默认执行状态为”已完成”,立即触发后面的done()方法,这就失去回调函数的作用了。dtd.promise()的目的,就是保证目前的执行状态—-也就是”未完成”—-不变,从而确保只有操作完成后,才会触发回调函数。
下面是 jQuery 的官方文档:
The deferred.promise() method allows an asynchronous function to prevent other code from interfering with the progress or status of its internal request. The Promise exposes only the Deferred methods needed to attach additional handlers or determine the state (then,done, fail, always,pipe, progress, and state), but not ones that change the state (resolve, reject, progress, resolveWith, rejectWith, and progressWith).
也就是说,deferred.promise() 只是阻止其他代码来改变这个 deferred 对象的状态。可以理解成,通过 deferred.promise() 方法返回的 deferred promise 对象,是没有 resolve ,reject, progress , resolveWith, rejectWith , progressWith 这些可以改变状态的方法,你只能使用 done, then ,fail 等方法添加 handler 或者判断状态。
deferred.promise() 改变不了 deferred 对象的状态,作用也不是保证目前的状态不变,它只是保证你不能通过 deferred.promise() 返回的 deferred promise 对象改变 deferred 对象的状态。如果我们这个地方直接返回 dtd,也是可以工作的,.done 的处理函数还是会等到 dtd.resolve() 之后才会执行.
具体在那篇博客的例子, 如果我们把代码改成如下的形式:
var dtd = $.Deferred(); // 新建一个deferred对象
var wait = function(dtd)
var tasks = function()
alert("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态
;
setTimeout(tasks,5000);
return dtd;
;
$.when(wait(dtd))
.done(function() alert("哈哈,成功了!"); )
.fail(function() alert("出错啦!"); );

这样的执行结果和先前返回 dtd.promise 的结果是一样的。
差别在什么地方呢?如果我们把 $.when 的这块的代码改成这样的:
var d = wait(dtd);
$.when(d)
.done(function() alert("哈哈,成功了!"); )
.fail(function() alert("出错啦!"); );
d.resolve();

我们会发现 alert(“哈哈,成功了!”) 会立即执行,“执行完毕”却需要5秒后才弹出来。
但是如果我们 wait 函数最后是 return dtd.promise() 这里 d.resolve() 就会报错了,因为对象 d 不存在 resolve() 方法。
同样如果我们把代码改成:
var dtd = $.Deferred(); // 新建一个deferred对象
var wait = function(dtd)
var tasks = function()
   alert("执行完毕!");
   dtd.resolve(); // 改变deferred对象的执行状态
   ;
   setTimeout(tasks,5000);
   return dtd.promise();
;
dtd.resolve();
$.when( wait(dtd))
.done(function() alert("哈哈,成功了!"); )
.fail(function() alert("出错啦!"); );

我们也可以发现 alert(“哈哈,成功了!”) 会立即执行,因为 dtd 这个 deferred 对象在被传入 wait 之前,已经被 resolve() 了,而 deferred 对象一旦被 resolve 或者 reject 之后,状态是不会改变的。
然后我们再把 $.wait 这块的代码改成:
$.when( wait(dtd))
.done(function() alert("哈哈,成功了!"); )
.fail(function() alert("出错啦!"); );
dtd.resolve();

我们也会发现 alert(“哈哈,成功了!”); 被立即执行,虽然 wait(dtd) 执行的时候, dtd 还没有被 resolve,而且 wait 方法返回的是 dtd.promise(), 但是 dtd 这个原始的 deferred 对象是暴露在外面的,我们还是可以从外面改变它的状态。
于是,如果我们真的不想让其他代码能改变 wait 方法内部的 deferred 对象的状态,那我们应该写成这样:
var wait = function()
var dtd = $.Deferred(); // 新建一个deferred对象
var tasks = function()
alert("执行完毕!");
   dtd.resolve(); // 改变deferred对象的执行状态
   ;
   setTimeout(tasks,5000);
   return dtd.promise();
;
$.when( wait())
.done(function() alert("哈哈,成功了!"); )
.fail(function() alert("出错啦!"); );

也就是不要把 deferred 直接暴露出来,最后返回 deferred.promise() ,让其他地方的代码只能添加 handler 。
参考技术B Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished. 参考技术C 请阅读英文原文追问

原文是什么?

jQuery的Deferred对象

jQuery.Deferred()

        创建一个延时对象Deferred。Deferred对象拥有三个状态resolved, reject, pending。三个状态分别对应三个触发函数deferred.resolve()/deferred.resolveWith(),deferred.reject()/deferred.rejectWith(),  deferred.notify()/deferred.notifyWith()。对象的状态可以通过deferred.state()对象进行判断,1.7之前判断三种状态分别使用 deferred.isResolved(),  deferred.isRejected(),对pendind状态没有专门的函数来判断,pending状态就是非resolved和rejected状态时deferred的状态。

      可以使用deferred.done(),deferred.fail()添加回调函数,回调函数在调用resolve(),reject()的时候执行。

      可以使用deferred.progress()添加回调函数,deferred.notify()/notifyWith()时执行。

 

jQuery.when()

 

jQuery.then()

以上是关于JQuery 的 deferred . promise对象的主要内容,如果未能解决你的问题,请参考以下文章

jQuery的Deferred对象

jquery中的 deferred之 deferred对象

jQuery异步框架探究2:jQuery.Deferred方法

jQuery异步框架探究2:jQuery.Deferred方法

jquery的defer

jQuery中的deferred对象的使用