深入解析jQuery中Deferred的deferred.promise()方法
来源: 阅读:859 次 日期:2016-07-06 10:32:13
温馨提示: 小编为您整理了“深入解析jQuery中Deferred的deferred.promise()方法”,方便广大网友查阅!

这篇文章主要介绍了jQuery中Deferred的deferred.promise()方法,提醒千万要注意deferred.promise()与jQuery的.promise() 实例方法的区别,需要的朋友可以参考下

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> 

更多信息请查看网络编程
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:hfpxwx
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map