简介


  在jQuery1.5.0版本引入,为了实现Deferred对象,jQuery改写了ajax。是由jQuery.Deferred()方法创建的链式对象。

  $.Deferred在jQuery代码自身四处被使用(promise、DOM ready、Ajax、Animation)

  

  特性:使用Deferred对象可以添加多个回调函数; 延迟特性,处理耗时操作问题

  • register multiple callbacks into callback queues
  • invoke callback queues
  • relay the success or failure state of any synchronous or asynchronous function

主要源码


jQuery1.9.1源码如下:

jQuery.extend({

    Deferred: function( func ) {
var tuples = [
// action, add listener, listener list, final state
[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
[ "notify", "progress", jQuery.Callbacks("memory") ]
],
state = "pending",
promise = {
state: function() {
.....
},
always: function() {
....
},
then: function( /* fnDone, fnFail, fnProgress */ ) {
           ....
},
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
.....
}
},
deferred = {}; // Keep pipe for back-compat
promise.pipe = promise.then; // Add list-specific methods
jQuery.each( tuples, function( i, tuple ) {
  ...
deferred[ tuple[0] + "With" ] = list.fireWith;
}); // Make the deferred a promise
promise.promise( deferred ); // Call given func if any
if ( func ) {
func.call( deferred, deferred );
} // All done!
return deferred;
}, // Deferred helper
when: function( subordinate /* , ..., subordinateN */ ) {
    ....
    return deferred.promise();
  } });

Callbacks 是jQuery的回调对象,用于添加回调、删除回调、执行回调等

jQuery.Callbacks = function( options ) {// Actual Callbacks object
self = {
// Add a callback or a collection of callbacks to the list
add: function() {
...
},
// Remove a callback from the list
remove: function() {
  ....
},
       ....
// Call all the callbacks with the given arguments
fire: function() {
self.fireWith( this, arguments );
return this;
},
// To know if the callbacks have already been called at least once
fired: function() {
return !!fired;
}
}; return self;
};

 

methods


  jQuery下两个方法:

  

$.Deffered() ——创建Deffered对象,var deferred = $.Deffered();

$.when()——为多个操作指定回调函数

  

  Deffered对象包含如下方法:

deferred.always()——执行回调函数,不管deffered 对象是 状态resolved或者是rejected
           (即不管成功或者失败,对应ajax中complete)(关于执行状态看下一章节) deferred.done()——当Deferred对象状态为resolved时执行回调函数 deferred.fail()——当Deferred对象状态为rejected时执行回调函数 deferred.then()——执行回调函数,deferred 对象是 状态resolved或者是rejected 或者是 in progress
deferred.isRejected()——判断状态是否为rejected

deferred.isResolved()——判断状态是否为resolved

deffered.state()——判断当前状态
deferred.promise()——返回Deferred的promise对象

deferred.reject()——reject a deferred对象,即将状态转为rejected( with the given args.)

deferred.rejectWith()——与上面reject的区别:with the given context and args. 下面类似

deferred.resolve()——即将状态转为resolve
              
deferred.resolveWith()——
deferred.notify()——call the progressCallbacks  

deferred.notifyWith()——  
 
 
deferred.pipe()——过滤参数
 

一般done/resolve fail/reject progress/notify 对应使用


执行状态


  Deffered对象三种执行状态: resolved(已完成)、未完成、rejected(失败)

  1. 如果执行状态是resovled,Deffered对象会立刻调用done()方法指定的回调函数

  2. 如果执行状态是rejected,Deffered对象会立刻调用fail()方法指定的回调函数

  3.  如果执行状态是未完成,Deffered对象会继续等待或者是调用progress()方法指定的回调函数

ajax及简单链式操作


eg:

ajax方式:

$.ajax("test.jsp").success(function(result){alert("success! data is :"+result);})  
.error(function(){alert("Error")})
           .complete(function(){alert("complete!")}); 或者: $.ajax({
url:"test.jsp",
success:function(result){alert("success! data is :"+result);},
     error: function(){alert("Error!");},
  complete:function(){alert("complete!")},
});

使用Deferred:

由于$.ajax 方法和$.get方法返回的是jqXHR对象(源自Deferred对象)因而上面的操作可以以下面的方式实现。

    $.ajax("test.jsp").done(function(result){alert("success! data is :"+result);})
.fail(function(){alert("Error")})
             .always(function(){alert("finished");});

注意:$.ajax()中jqXHR.success(), jqXHR.error(), jqXHR.complete(), 在jquery 1.8中已经弃用,应该使用done(),fail()和always()

done/resolve   fail/reject   progress/notify


done/resolve

var dfd = $.Deferred();

dfd.done(function(){
console.log("###############")
}); $("button").on("click",function(){
dfd.resolve();
});

点击按钮,输出  ###############

fail/reject

var dfd = $.Deferred();

dfd.fail(function(){
console.log("###############")
}); $("button").on("click",function(){
dfd.reject();
});

点击按钮,输出  ###############

progress/notify

eg1:

var dfd = $.Deferred();

dfd.progress(function(){
console.log("###############")
}); $("button").on("click",function(){
dfd.notify();
});

点击按钮,输出  ###############

eg2:使用notify间隔的执行回调函数

var dfd = $.Deferred();

dfd.progress(function(){
console.log("###############");
}); $("button").on("click",function(){
setInterval(function(){
dfd.notify();
},1000); });

点击按钮,每1s输出一次##################

执行多个回调函数


eg1:

    $.ajax("test.jsp").done(function(){console.log("the first callback");})
.done(function(){console.log("the second callback");})
.done(function(){console.log("the third callback");})
.fail(function(){console.log("Error")}); 或者: $.ajax("test.jsp").success(function(){console.log("the first callback");})
           .success(function(){console.log("the second callback");})
           .success(function(){console.log("the third callback");})
           .error(function(){console.log("Error")});

输出:

the first callback
the second callback
the third callback

eg2:

deferred对象的done方法定义如下:deferred.done( doneCallbacks [, doneCallbacks ] ) 可以传入 array of functions

success也可达到相同效果,但是已弃用不建议使用

     $.ajax("test.jsp").done([f1,f2,f3],[f2,f3])
.done(function(){console.log("the fourth callback");})
.fail(function(){alert("Error")});
function f1(){
console.log("the first callback");
}
function f2(){
console.log("the second callback");
}
function f3(){
console.log("the third callback");
}

输出结果如下:

the first callback
the second callback
the third callback
the second callback
the third callback
the fourth callback

eg3: 使用jQuery.Deferred()创建Deferred对象

简单使用done方法和resolve方法

function f1(){
console.log("the first callback");
}
function f2(){
console.log("the second callback");
}
function f3(){
console.log("the third callback");
} var dfd = $.Deferred();
dfd.done([f1,f2,f3],[f2,f3])
.done(function(){console.log("finished");});
$("button").on("click",function(){
dfd.resolve();
});

点击button,输出:

the first callback
the second callback
the third callback
the second callback
the third callback
finished

eg4. 给resolve添加args

function f1(arg){
console.log(arg+"the first callback");
}
function f2(arg){
console.log(arg+"the second callback");
}
function f3(arg){
console.log(arg+"the third callback");
} var dfd = $.Deferred();
dfd.done([f1,f2,f3],[f2,f3])
.done(function(){console.log("finished");})
.always(function(arg){console.log(arg+"end");}); $("button").on("click",function(){
dfd.resolve("###############");
});

输出如下:

###############the first callback
###############the second callback
###############the third callback
###############the second callback
###############the third callback
finished
###############end

then和pipe


 pipe

使用pipe可以过滤参数,但是jQuery 1.8后已经启用pipe方法,建议使用then

pipe方法定义为:deferred.pipe( [doneFilter ] [, failFilter ] [, progressFilter ] )    returns a new promise

eg1:一次性定义done fail 和progress

function f1() {
console.log('done');
}
function f2() {
console.log('fail');
}
function f3() {
console.log('progress');
}
var deferred = $.Deferred();
deferred.pipe(f1, f2, f3);
$("button").on("click",function(){
deferred.reject();
});

点击按钮,输出 fail, 可以根据需要修改deferred.reject 为resolve或者是notify

eg2:

var dfd = $.Deferred();
dfd.pipe(function(arg){return "(*^__^*)"+arg;}); dfd.done(function(arg){
console.log(arg)
}); $("button").on("click",function(){
dfd.resolve("###############");
});

点击按钮输出:

(*^__^*)###############

eg3:

var dfd = $.Deferred();
argFilter = dfd.pipe(null, function(arg){return "(*^__^*)"+arg;}); argFilter.fail(function(arg){
console.log(arg)
}); $("button").on("click",function(){
dfd.reject("###############");
});

输出结果同上

 then 

deferred.then( [doneFilter ] [, failFilter ] [, progressFilter ] )

function f1() {
console.log('done');
}
function f2() {
console.log('fail');
}
function f3() {
console.log('progress');
}
var deferred = $.Deferred();
deferred.then(f1, f2, f3);
$("button").on("click",function(){
deferred.reject();
});

效果同pipe

 when为多个操作指定回调函数


jQuery.when(deferreds);

如果传入单个deferred, 返回promise对象,后面可以链式添加then等方法

如果传入多个deferred,返回a new master deferred对象,该对象集合所有deferred对象的状态,如果所有deferred对象是resollve则结果是resolve,如果有一个是reject则结果是reject

eg1:

$.when($.ajax("test.jsp")).done(function(){console.log("done");});

结果:

GET http://localhost:8080/javascript/jQuery/test.jsp  200 OK 83ms    

done

eg2:

function f1() {
console.log('done');
}
function f2() {
console.log('fail');
}
function f3() {
console.log('progress');
}
$.when($.ajax("test.jsp")).then(f1,f2,f3);

结果同上

eg3:

$.when($.ajax("test.jsp"),$.ajax("demo.jsp")).done(function(){console.log("done");});

结果:

GET http://localhost:8080/javascript/jQuery/test.jsp  200 OK 83ms    

GET http://localhost:8080/javascript/jQuery/demo.jsp   200 OK 460ms    

done

eg4:

 <style>
div {
height: 50px;
width: 50px;
float: left;
margin-right: 10px;
display: none;
background-color: #090;
}
</style>
<button>button</button>
<div></div>
<div></div>
<div></div>
<div></div>
var effect = function() {
return $( "div" ).fadeIn( 800 ).delay( 1200 ).fadeOut();
}; $( "button" ).on( "click", function() {
$.when( effect() ).done(function() {
console.log("finished");
});
});

effect()方法执行完后输出 finished;

.promise()


.promise([type][,target])  return a promise object   当所有与其相关的action结束后变为resolve状态

(The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended.)

eg1:

var button = $( "<button>" );
button.promise().done(function( arg ) {
console.log( this === button && arg === button ); //true
});

eg2:

 <style>
div {
height: 50px;
width: 50px;
float: left;
margin-right: 10px;
display: none;
background-color: #090;
}
</style>
<button>button</button>
<div></div>
<div></div>
<div></div>
<div></div>
$( "button" ).on( "click", function() {

  $( "div" ).each(function( i ) {
$( this ).fadeIn().fadeOut( 1000 * ( i + 1 ) );
}); $( "div" ).promise().done(function() {
console.log("finished");
});
});

animation结束后输出finished,效果等价于when 中的eg4

相关:http://api.jquery.com/category/deferred-object/

     http://www.cnblogs.com/littledu/articles/2811728.html

   http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

jQuery deferred学习笔记的更多相关文章

  1. jQuery源代码学习笔记_工具函数_noop/error/now/trim

    jQuery源代码学习笔记_工具函数_noop/error/now/trim jquery提供了一系列的工具函数,用于支持其运行,今天主要分析noop/error/now/trim这4个函数: 1.n ...

  2. jQuery的学习笔记4

    JQuery学习笔记3 2.9属性选择器 属性选择器就是根据元素的属性和属性值作为过滤条件,来匹配对应的DOM元素.属性选择器一般都以中括号作为起止分界符 它的形式如下: [attribute] [a ...

  3. jQuery的学习笔记2

    jQuery学习笔记 Day two Chapter two 选择器 类选择器 语法结构:$(“.classname”) javascript里面没有类选择器所以这个时候使用jQuery会更加的简便 ...

  4. jQuery的学习笔记

    JQuery学习笔记 Chapter one初识jQuery 1.2测试jQuery 在jQuery库中,$是jQuery的别名,如:$()相当于jQuery() 注意:在使用JQuery进行开发的时 ...

  5. jQuery 基础学习笔记总结(一)

    Jquery 学习笔记 总结 感想: 此前在做站点时用到过jquery相关,特别是Ajax相关技术.但是并没有系统的进行学习和了解Jquery的强大的功能,趁这几天跟着资料基本的了解下Jquery的特 ...

  6. Jquery Mobile 学习笔记(一)

    1.模拟器,IOS:XCODE GENYMOTION  ANDROID:ECLIPSE GENYMOTION 2.jquery mobile data-role=page 代表一个页面 data-po ...

  7. 【jQuery UI 1.8 The User Interface Library for jQuery】.学习笔记.4.Tabs控件

    之前,我们已经介绍了 jQuery UI 库,CSS 框架.下面,我们将学习这些有增强可视化效果,高度可配置的用户交互组件. Tab 的特性是,点击 tab 后,会高亮该 tab,并显示他的关联con ...

  8. Jquery mobile 学习笔记

    最近学习移动开发,接触到了phonegap,然后又需要开始学习jquery mobile.掌握两者是开发轻应用的前提 在学习jquery mobile中,遇到了许多问题让初学者很是头疼,无意间找到这个 ...

  9. jQuery api 学习笔记(1)

      之前自己的jquery知识库一直停留在1.4的版本,而目前jquery的版本已经更新到了1.10.2了,前天看到1.10中css()竟然扩充了那么多用法,这2天就迫不及待的更新一下自己的jquer ...

随机推荐

  1. Java Math 类中的新功能--浮点数

    Java™语言规范第 5 版向 java.lang.Math和 java.lang.StrictMath添加了 10 种新方法,Java 6 又添加了 10 种.这个共两部分的系列文章的 第 1 部分 ...

  2. SPOJ 3048 - DNA Sequences LCS

    给出两个字符串(不长于1000),求最长公共子序列,要求:从每个串中取必须取连续k (1<=k<=100)个数 [LCS]一开始自己想用DP加一维[len]用来表示当前已经取了连续len个 ...

  3. Poj 3368 Frequent values

    /* 线段树区间合并 维护几个信息 到时候乱搞一下就好了 开始T了 有一种情况可以不用递归 直接算出来 */ #include<iostream> #include<cstdio&g ...

  4. @ManyToMany 两个表多对多关联

    两个表属于多对多关系 如 Teacher <=> Student 表teacher 主键 id 表student 主键id 中间关联表 teacher_student 两个字段 t_id ...

  5. C#多线程lock解决数据同步

    1.代码实例: public class ThreadTest4 { public static void Init() { //多个线程修改同一个值,使用lock锁解决并发 ; i < ; i ...

  6. 你好,C++(31)我终于找到对象啦!6.1 从结构化设计到面向对象程序设计

    第6章 当C++爱上面向对象 很多第一次进入C++世界的人都会问:C++中的那两个加号到底是什么意思啊? C++是由C语言发展而来的,它比C语言多出的两个加号,实际上是C语言的自增操作符,表示C++语 ...

  7. openstack VM可以ping外部网络,但是外部网络ping不通VM

    经过无数次的尝试,终于搭建好了完整的Openstack,本来VM可以获取到IP地址,但是等到我大功告成的时候,突然发现外部网络却不能ping进VM,我可是整整折腾了我几个通宵,这是哭啊.然而,皇天不负 ...

  8. 如何使用LoadRunner监控Windows

    1.监视连接前的准备工作   1)进入被监视windows系统,开启以下二个服务Remote Procedure Call(RPC) 和Remote Registry Service (开始—)运行 ...

  9. Centos7下Intel与AMD双显卡驱动的安装

      前2天,在Nvidia单显卡上成功安装上了NVIdia的驱动,一时兴起,拿出另外的一个HP笔记本也准备装上驱动,悲催的是HP的显卡是AMD的,更加.更加悲催的是还是Intel+AMD的双显卡.网络 ...

  10. 使用微妙计算PHP脚本执行时间

    在PHP中,大多数的时间格式都是以UNIX时间戳表示的,而UNIX时间戳是以s(秒)为最小的计量时间的单位.这对某些应用程序来说不够精确,所以可以调用microtime()返回当前UNIX时间戳和微妙 ...