深入解析jQuery中Deferred的deferred.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>
(0)

相关推荐

  • jQuery的promise与deferred对象在异步回调中的作用

    一.前言 为了让前端们从回调的地狱中回到天堂, jQuery 也引入了 Promise 的概念. Promise 是一种令代码异步行为更加优雅的抽象,有了它,我们就可以像写同步代码一样去写异步代码. jQuery 从1.5版本开始实现了 CommonJS Promise/A 规范这一重量级方案,不过没有严格按照规范进行实现,有一些API上的差异. 好,让我们来看看他们的特性吧( 本文示例基于jquery 1.8版本以上 ). 二.示例 以前写动画时,我们通常是这么干的: $('.animateE

  • 以jQuery中$.Deferred对象为例讲解promise对象是如何处理异步问题

    Promises是一种令代码异步行为更加优雅的抽象,它很有可能是JavaScript的下一个编程范式,一个Promise即表示任务结果,无论该任务是否完成. 在一些现代浏览器中已经提供了原生的Promise对象,其遵循Promise/A+标准.在jQuery1.5+,提供了$.Deferred(其可以被转化为promise对象).很多知名的框架中,也提供了promise对象.promise对象在javascript中已经是一种很重要的模式,它在解决异步问题时表现出的优雅,正是javascript

  • 详解JavaScript异步编程中jQuery的promise对象的作用

    Promise, 中文可以理解为愿望,代表单个操作完成的最终结果.一个Promise拥有三种状态:分别是unfulfilled(未满足的).fulfilled(满足的).failed(失败的),fulfilled状态和failed状态都可以被监听.一个愿望可以从未满足状态变为满足或者失败状态,一旦一个愿望处于满足或者失败状态,其状态将不可再变化.这种"不可改变"的特性对于一个Promise来说非常的重要,它可以避免Promise的状态监听器修改一个Promise的状态导致别的监听器的行

  • 在jQuery1.5中使用deferred对象 着放大镜看Promise

    引言在那篇经典的关于jQuery1.5中Deferred使用方法介绍的文章中(译文见这里),有下面一段描述: $.ajax() returns an object packed with other deferred-related methods. I discussed promise(), but you'll also find then(), success(), error(), and a host of others. You don't have access to the c

  • jQuery Deferred和Promise创建响应式应用程序详细介绍

    这篇文章,我们一起探索一下 JavaScript 中的 Deferred 和 Promise 的概念,它们是 JavaScript 工具包(如Dojo和MochiKit)中非常重要的一个功能,最近也首次亮相于 流行的 JavaScript 库 jQuery(已经是1.5版本的事情了). Deferred 提供了一个抽象的非阻塞的解决方案(如 Ajax 请求的响应),它创建一个 "promise" 对象,其目的是在未来某个时间点返回一个响应.如果您之前没有接触过 "promis

  • Jquery promise实现一张一张加载图片

    Promise是CommonJS的规范之一,拥有resolve.reject.done.fail.then等方法,能够帮助我们控制代码的流程,避免函数的多层嵌套.如今异步在web开发中越来越重要,对于开发人员来说,这种非线性执行的编程会让开发者觉得难以掌控,而Promise可以让我们更好地掌控代码的执行流程,jQuery等流行的js库都已经实现了这个对象,年底即将发布的ES6也将原生实现Promise. 在javascript设计模式实践之代理模式--图片预加载中用代理模式实现了图片预加载功能.

  • jQuery中的Deferred和promise 的区别

    Deferred和Promise之间有什么区别呢? promise 一个promise就是一个由 异步函数返回的对象 .当你想要自己编写一个这样的函数时你需要使用一个deferred. var promise = $.ajax({ url: "/myServerScript" }); promise.done(mySuccessFunction); promise.fail(myErrorFunction); var promise = $.ajax({ url: "/myS

  • Jquery中使用show()与hide()方法动画显示和隐藏图片

    (1)功能描述 在页面中单击"显示"连接,通过show()方法以动画的方式显示一幅图片,同时在方法中执行一个回调函数,用于改变图片的边框样式:单击已显示的图片时,通过hide()以动画的方式隐藏该图片. (2)实现代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.d

  • JQuery中操作Css样式的方法

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

  • jQuery中页面返回顶部的方法总结

    当页面过长时,通常会在页面下方有一个返回顶部的button,总结一下,大概三种实现方法,下面说下各方法及优缺点. 方法一 锚点定位 <a href="#" class="top" id="top">返回頂部</a> 这种方法设置方便,但缺点是会刷新页面(我是在同事的乐视手机上发现的). 方法二 window.scrollTo(x,y) <a href="javascript:scrollTo(0,0)&qu

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

    本文实例讲述了JQuery中attr方法和removeAttr方法用法.分享给大家供大家参考.具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"

  • 修改jquery中dialog的title属性方法(推荐)

    好久都没办法尝试成功 在网上找的经测试也不行 于是在官方文档上看到了 结果终于成功了 $("#overTime").dialog({ autoOpen: false, width: 400, modal: true, title: "Dialog Title", buttons: { "确定": function () { }, "取消": function () { } } }); 在初始化的时候要写title属性(官方文档

  • jquery中live()方法和bind()方法区别分析

    本文实例讲述了jquery中live()方法和bind()方法区别.分享给大家供大家参考,具体如下: live()不受加载时间顺序的影响,只要查找能够配对上就能够绑定对应的事件,而bind方法只有在第一次被加载的时候才绑定时间,如果代码之后再加载配对的元素,则不能绑定对应的事件 $("#manual_disconnect").live("click", function(){ connectionProfile("0"); }); $("

  • 深入解析Java中反射中的invoke()方法

    先讲一下java中的反射: 反射就是将类别的各个组成部分进行剖析,可以得到每个组成部分,就可以对每一部分进行操作 反射机制应用场景:逆向代码.动态生成类框架等,使用反射机制能够大大的增强程序的扩展性. 反射的基本步骤:首先获得Class对象,然后实例化对象,获得类的属性.方法或者构造函数,最后访问属性.调用方法.调用构造函数创建对象.而invoke()方法就是用来执行指定对象的方法. 在比较复杂的程序或框架中来使用反射技术,可以简化代码提高程序的复用性. 讲的是Method类的invoke()方

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

    deferred.promise() 和 .promise() 这两个API语法几乎一样,但是有着很大的差别.deferred.promise()是Deferred实例的一个方法,他返回一个Deferred.Promise实例.一个Deferred.Promise对象可以理解为是deferred对象的一个视图,它只包含deferred对象的一组方法,包括:done(),then(),fail(),isResolved(), isRejected(), always(),这些方法只能观察一个def

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

    复制代码 代码如下: 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中的$(window)与$(document)的用法区别

    [window对象] 它是一个顶层对象,而不是另一个对象的属性,即表示浏览器中打开的窗口.   1.属性 defaultStatus 缺省的状态条消息 document 当前显示的文档(该属性本身也是一个对象) frame 窗口里的一个框架((FRAME>)(该属性本身也是一个对象) frames array 列举窗口的框架对象的数组,按照这些对象在文档中出现的顺序列出(该属性本身也是一个 对象) history 窗口的历史列表(该属性本身也是一个对象) length 窗口内的框架数 locat

随机推荐