简介


  在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. VS项目属性配置实验过程

    (原创,转载注明出处:http://www.cnblogs.com/binxindoudou/p/4017975.html ) 一.实验背景 cocos2d-x已经发展的相对完善了,从项目的创建.编译 ...

  2. Creating a simple static file server with Rewrite--reference

    Today, I’d like to take a quick moment to demonstrate how to make a simple file server using Rewrite ...

  3. iOS开发UI篇-懒加载、重写setter方法赋值

    一.懒加载 1.懒加载定义 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再 ...

  4. iOS开发系列之运动事件

    前面我们主要介绍了触摸事件以及由触摸事件引出的手势识别,下面我们简单介绍一下运动事件.在iOS中和运动相关的有三个事件:开始运动.结束运动.取消运动. 监听运动事件对于UI控件有个前提就是监听对象必须 ...

  5. 《Android开发艺术探索》读书笔记 (7) 第7章 Android动画深入分析

    本节和<Android群英传>中的第七章Android动画机制与使用技巧有关系,建议先阅读该章的总结 第7章 Android动画深入分析 7.1 View动画 (1)android动画分为 ...

  6. retrofit2 okhttp3 RxJava butterknife 示例

    eclipse的jar包配置 eclipse中貌似用不了butterknife buildToolsVersion "23.0.2" defaultConfig { applica ...

  7. Android MediaCodec 使用例子

    Android MediaCodec 使用例子 下面的例子是使用MediaCodec 录制到文件的例子. 1 public class AvcEncoder { private MediaCodec ...

  8. ASPNET5的依赖注入

    ASP.NET5设计的时候就是以DI为基础的,它可以利用内建的框架在Startup类的方法中,把依赖注入进去.应用服务也可以被配置的注入.默认的服务容器提供一些基本的功能,它并不打算代替现代主流的DI ...

  9. div 显示滚动条

    overflow-x:auto    显示横向滚动条 overflow-y:hidden 隐藏纵向滚动条 引用此class,只显示横向的滚动条 .max{ margin:auto; overflow- ...

  10. 状态开关按钮(ToggleButton)及按钮(Swich)的使用

    状态开关按钮(ToggleButton)和开关(Switch)也是由Button派生出来的,因此它们本质上都是按钮,Button支持的各种属性.方法也适用于ToggleButton和Switch.从功 ...