深入解析jQuery中Deferred的deferred.promise()方法_jquery

deferred.promise() 和 .promise()

这两个API语法几乎一样,但是有着很大的差别。deferred.promise()是Deferred实例的一个方法,他返回一个Deferred.Promise实例。一个Deferred.Promise对象可以理解为是deferred对象的一个视图,它只包含deferred对象的一组方法,包括:done(),then(),fail(),isResolved(), isRejected(), always(),这些方法只能观察一个deferred的状态,而无法更改deferred对象的内在状态。这非常适合于API的封装。例如一个deferred对象的持有者可以根据自己的需要控制deferred状态的状态(resolved或者rejected),但是可以把这个deferred对象的Promise对象返回给其它的观察者,观察者只能观察状态的变化绑定相应的回调函数,但是无法更改deferred对象的内在状态,从而起到很好的隔离保护作用。

deferred.promise()

$(function(){
  //
  var deferred = $.Deferred();
  var promise = deferred.promise(); 

  var doSomething = function(promise) {
    promise.done(function(){
      alert('deferred resolved.');
    });
  }; 

  deferred.resolve();
  doSomething(promise);
})

deferred.promise()也可以接受一个object参数,此时传入的object将被赋予Promise的方法,并作为结果返回。

// Existing object
var obj = {
 hello: function( name ) {
  alert( "Hello " + name );
 }
},
// Create a Deferred
defer = $.Deferred(); 

// Set object as a promise
defer.promise( obj ); 

// Resolve the deferred
defer.resolve( "John" ); 

// Use the object as a Promise
obj.done(function( name ) {
 this.hello( name ); // will alert "Hello John"
}).hello( "Karl" ); // will alert "Hello Karl" 

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 。

.promise()

首先这不是Deferred实例的方法!该方法是jQuery实例的方法。该方法用于一组类型的动作(例如动画)全部完成后返回一个Promise对象,供事件监听器监听其状态并执行相应的处理函数。

该方法接受两个可选参数:.promise( [type,] [target] )

type:队列的类型,默认值是fx,fx即jQuery对象的动画.
targetObject :要赋予Promise行为的对象,

这两个参数是可选的。其中第一个参数(我)目前除了fx还没有找到其他的值类型。因此一般都是用于动画的监控,在动画完成后做一些操作。

例子:没有动画效果直接返回一个resolved状态的promise对象

var div = $( "<div />" ); 

div.promise().done(function( arg1 ) {
 // 将会被马上触发
 alert( this === div && arg1 === div );
}); 

例子:在动画效果全部完成后触发done()监听函数

<!DOCTYPE html>
<html>
<head>
 <style>
div {
 height: 50px; width: 50px;
 float: left; margin-right: 10px;
 display: none; background-color: #090;
}
</style>
 <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body> 

<button>Go</button>
<p>Ready...</p>
<div></div>
<div></div>
<div></div>
<div></div>
<script>
$("button").bind( "click", function() {
 $("p").append( "Started...");
 //每个div执行动画效果
 $("div").each(function( i ) {
  $( this ).fadeIn().fadeOut( 1000 * (i+1) );
 });
 //$("div")包含一组div,在所有的div都完成自己的动画效果后触发done()函数
 $( "div" ).promise().done(function() {
  $( "p" ).append( " Finished! " );
 });
});
</script> 

</body>
</html>

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索javascript
, jquery
, js
, promise
deferred
deferred.promise、promise deferred模式、promise deferred区别、promise和deferred、deferred与promise,以便于您获取更多的相关知识。

时间: 2024-12-21 10:57:39

深入解析jQuery中Deferred的deferred.promise()方法_jquery的相关文章

JQuery中操作Css样式的方法_jquery

复制代码 代码如下: //1.获取和设置样式 $("#tow").attr("class")获取ID为tow的class属性 $("#two").attr("class","divClass")设置Id为two的class属性. //2.追加样式 $("#two").addClass("divClass2")为ID为two的对象追加样式divClass2 //3.移除

解析prototype,JQuery中跳出each循环的方法_jquery

复制代码 代码如下: function chk(){        var flag=true;        var msg='';        var tips={'username':'姓名','tel':'电话','company':'公司名称','loupan_name':'楼盘名','sdate':'团购时间','content_1':'团购内容'};        $$('.required').each(function(el){            if($F(el).bl

JQuery中解决重复动画的方法_jquery

下面我们就来总结一下几个JQuery中解决重复动画的办法 ,这里有几个常见的动画效果,它们分别是:图片滚动轮播,回到页面顶部,联级菜单滑出,手风琴. 图片滚动: $("#banner-min-img1").mouseover(function (){ $("#banner-img").animate({left:"0px"},300)} $("#banner-min-img2").mouseover(function (){

实例解析jQuery中如何取消后续执行内容_jquery

<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> //点击a标签,不进行页面跳转 window.onload = function () { var obj = document.getElementById("myhref"); obj.o

jQuery中filter(),not(),split()使用方法_jquery

filter()和not(): 复制代码 代码如下: <script type="text/javascript"> $(document).ready(function() { //输出 hello alert($("p").filter(".selected").html()); //输出 How are you? alert($("p").not(".selected").html());

jquery中对于批量deferred的处理方法

 这篇文章主要介绍了jquery中对于批量deferred的处理方法,有需要的朋友可以参考一下 此代码仿照jquery源码中$.when()的实现 代码如下: function test(i) {     var dfd = $.Deferred();     if(i%2 == 0) {         console.log("resolve " + i);         dfd.resolve();     } else {         console.log("

解析prototype,JQuery中跳出each循环的方法

 这篇文章主要介绍了在prototype,JQuery中跳出each循环的方法.需要的朋友可以过来参考下,希望对大家有所帮助   代码如下: function chk(){         var flag=true;         var msg='';         var tips={'username':'姓名','tel':'电话','company':'公司名称','loupan_name':'楼盘名','sdate':'团购时间','content_1':'团购内容'};  

浅析jQuery中常用的元素查找方法总结

本篇文章是对jQuery中常用的元素查找方法进行了详细的总结和介绍,需要的朋友参考下   $("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个id值是myElement所以得到的是唯一的元素 $("div") 选择所有的div标签元素,返回div元素数组 $(".myClass")   选择使用myClass类的css的所有元素 $("*") 选择文档中的所有的元素,可以运用

JQuery中attr方法和removeAttr方法用法实例

  本文实例讲述了JQuery中attr方法和removeAttr方法用法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:

jquery中get,post和ajax方法的使用小结

 本篇文章主要是对jquery中get,post和ajax方法的使用进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 在JQuery中可以使用get,post和ajax方法给服务器端传递数据   get方法的使用(customForGet.js文件):   function verify(){ //1.获取文本框的数据   //通过DOM的方式获取 //document.getElementByIdx("userName"); //通过JQuery的方式获取 var jq