简介


  在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. (五)带属性值的ng-app指令,实现自己定义模块的自己主动载入

    如今我们看下怎样使用带属性值的ng-app命令,让ng-app自己主动载入我们自己定义的模块作为根模块. <!DOCTYPE html> <html> <head> ...

  2. How To Cluster Rabbit-MQ--reference

    Foreword This explanation of clustering Rabbit-MQ assumes that you’ve had some experience with Rabbi ...

  3. chmod -x chmod的N种解法

    声明:该文章摘自陈皓的酷壳. 问题: 如果某天你的Unix/Linux系统上的chomd命令被某人去掉了x属性(执行属性),那么,你如何恢复呢? 参考答案: 1)重新安装.对于Debian的系统: s ...

  4. WebView使用详解(一)——Native与JS相互调用(附JadX反编译)

    念念不忘,必有回响,永远坚持你所坚持的! 一直在用WebView,还没有系统的总结过它的用法,下面就系统的总结下,分享给大家 一.基本用法 1.加载在线URL void loadUrl(String ...

  5. uva 11324 The Largest Clique (Tarjan+记忆化)

    /*每个环 要么不选 要么全选 可缩点 就得到一个GAD图 然后搞搞算出最大路径*/ #include<iostream> #include<cstdio> #include& ...

  6. IIS 配置好了,为什么网站打开一片空白?

    方法如下: 进入:控制面板 - 卸载程序 - 打开或关闭Windows功能 如果访问任何不存在页面或页面出错时空白: Internet 信息服务 - 万维网服务 - 常见 HTTP 功能 - HTTP ...

  7. Dedecms当前位置{dede:field name='position'/}修改

    这个实在list_article.htm模板出现的,而这个模板通过loadtemplage等等一系列操作是调用的include 下的arc.archives.class.php $this->F ...

  8. 【转】 分析iOS Crash文件:符号化iOS Crash文件的3种方法

    当你的应用提交到AppStore或者各个渠道之后,请问你多久会拿到crash文件?你如何分析crash文件的呢? 上传crash文件 你的应用应当有模块能够在应用程序crash的时候上传crash信息 ...

  9. nodejs新手教程中upload file的问题

    可参见: http://cnodejs.org/topic/50234890f767cc9a51f88481 request.setEncoding("utf8");应注释掉.

  10. Hibernate 事件监听

    事件监听是JDK中常见的一种模式. Hibernate中的事件监听机制可以对Session对象的动作进行监听,一旦发生了特殊的事件,Hibernate就会调用监听器类中的事件处理方法.在某些功能的设计 ...