三言两语说一下jquery中deferred对象
deferred对象是什么?能吃吗
不能吃。简单的来说,deferred对象是从jquery-1.5开始引入的一个新东东,是一个能使我们更方便的处理各种延时或异步事件(也不知道用事件这个词合不合理,我也不知道在怎么讲啦)的工具。我们知道这些延时或异步事件最终都是要靠回调函数来处理的,deferred对象的出现就是为了能帮助我们更好的管理这些回调函数,并且能使我们的写出的代码更加清爽、可读。
说这些有什么用,举个例子呗
额。。。好吧。说到异步,脑子里的第一反应当然是ajax了。先看下jquery中一个典型的ajax写法:
$.ajax({ url:'test.php', success:function(){alert('ok')}, error:function(){alert('error')} });
然而引入deferred对象后,jquery-1.5及其以后的版本中就可以这样写了:
$.ajax({url:'test.php'}).done(function(){alert('ok')}).fail(function(){alert('error')});
或者更清晰的写法:
var dfd = $.ajax({url:'test.php'}); dfd.done(function(){alert('ok')}) .fail(function(){alert('error')}) .done(function(){alert('ok again')})//可以有多个回调 .fail(function(){alert('error again')})//可以有多个回调
是的,ajax方法返回的对象可以使用done(),fail()这样的方法了,done()方法是ajax请求成功时会调用的方法,相当于原来的ajax参数中的success,fail()方法是ajax请求失败时会调用的方法,相当于原来ajax参数中的error。为什么可以使用这样的方法?因为从1.5版本以后,jquery的ajax方法(也包括get、post等)返回的不再是xhr对象,而是deferred对象了,done(),fail()等方法就是deferred对象提供的。至于deferred对象完整的方法及属性可以参考jquery的官方手册。
所以这是deferred对象的第一个好处:我们可以像注册事件一样,注册回调函数,并且一个延时或异步的事件可以有多个回调函数,如果需要逻辑很复杂的回调处理,这就很方便了啊亲~
然后呢?
然后就是不仅可以一个事件有多个回调函数,也可以多个事件共享一个回调函数。举个例子:
$.when( $.get('a.php'), $.get('b.php'), $.post('c.php') ).done(function(){alert('ok')})//三个ajax请求都成功时才调用 .fail(function(){alert('error')});//只要有一个ajax请求失败就会调用
$.when()可以接受一个或多个deferred对象,并且使他们共享一个回调函数(当然多个也是可以的,只要再接着注册done或fail方法就行啦),呵呵,没有deferred对象前要实现这样的效果可能要用复杂的多层回调函数嵌套去做,现在是不是很简单了呢。
前面说的deferred对象都是jquery内部方法返回的,并且他们成功或失败的状态也是jquery给出的。我们还可以手动创建我们的自己的deferred对象,并且控制它的状态。
var dfd = $.Deferred();//是的,这样我们就创建了一个Deferred对象
deferred对象创建出来后又该干什么呢?当然是给它注册回调函数啦。说到底,deferred对象就是一个能根据它的不同的状态调用注册在它上面的不同的回调函数的东西。它的状态的改变是延时的或异步的,也可以是手动改变的,状态变了后,相应的回调函数就会执行。
var dfd = $.Deferred(); //创建一个deferred对象 dfd.done(function(){alert('ok')});//给它注册一个代表成功的回调函数 setTimeout(function(){ dfd.resolve();//5秒后手动把我们建立的那个deferred对象的状态改为成功,状态改变后,用done()注册的回调函数会立即执行 },5000);
这里再说一下deferred对象的状态。deferred对象共有三种状态,分别是:成功、失败、既不是成功也不是失败。deferred对象会监听成功和失败这两种状态的改变,从而调去相应的回调函数。我们新建一个deferred对象时,它的初始状态是既不是成功也不是失败的,这种状态不会被监听。要注意的是,deferred对象的状态只能改变一次,例如把一个deferred对象从初始状态改为成功状态后,你不能再又把它改为失败状态。
要手动把一个deferred对象的状态改为成功,可以使用它的resolve()方法,要把它的状态改为失败,则可以使用reject()方法。
promise对象
使用deferred对象的promise()方法能获得一个promise对象。那这个promise对象是什么滴干活呢?是这样的,promise对象就相当于一个简化版的deferred对象,它把一些能够改变deferred对象状态的方法都去掉了,只提供了几个绑定回调函数以及查看当前状态的方法,例如done,fail,always,state等。所以我们写程序的时候暴露给外面的最好是一个deferred对象的promise对象,而不是那个直接的deferred对象,这样就能防止外部的程序修改deferred对象的状态啦。
function creatDeferred(){//创建Deferred对象 var dfd = $.Deferred(); setTimeout(function(){ dfd.resolve(); },3000); return dfd.promise();//返回一个promise对象 } var dfd = creatDeferred();创建一个Deferred对象,实际上得到的是一个promise对象 dfd.done(function(){alert('ok')}); dfd.resolve();//该句无效,因为promise对象是不能改变Deferred对象的状态的
总结
1、deferred对象可以把异步或延迟当作平常的事件一样来注册它们的回调函数,使异步或延迟编程的回调函数的管理更加清晰和明朗。
2、一个deferred对象可以有多个回调函数。
3、多个deferred对象可以共用一个或多个回调函数。
4、可以手动改变deferred对象的状态,就像事件中的手动触发事件一样,这样所有的东西都可以当做deferred对象来对待,然后方便的使用它提供的各种方法。