一、什么是deferred对象?
开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。
通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。
但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。
简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是"延迟",所以deferred对象的含义就是"延迟"到未来某个点再执行。
它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。
二、jQuery Deferred用法小结:
(1) $.Deferred() 生成一个deferred对象。
(2) deferred.done() 指定操作成功时的回调函数
(3) deferred.fail() 指定操作失败时的回调函数
(4) deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
(5) deferred.resolve() 手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。
(6)deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。
(7) $.when() 为多个操作指定回调函数。
除了这些方法以外,deferred对象还有二个重要方法,上面的教程中没有涉及到。
(8)deferred.then()
有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。
$.when($.ajax( "/main.php" ))
.then(successFunc, failureFunc );
如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。
(9)deferred.always()
这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
$.ajax( "test.html" )
.always( function() { alert("已执行!");} );
三、简单代码实现:
1 function Deferred(){ 2 this.state = 0; 3 this.doneQueue = []; 4 this.failQueue = []; 5 } 6 7 Deferred.prototype = { 8 constructor : Deferred, 9 promise : function(){ 10 return this; 11 }, 12 done : function(callback){ 13 this.doneQueue.push(callback); 14 if( this.state != 0 ){ 15 this._finish(); 16 } 17 return this; 18 }, 19 resolve : function(){ 20 this.state = 1; 21 this.args = arguments; 22 this._finish(); 23 }, 24 reject : function(){ 25 this.state = 2; 26 this.args = arguments; 27 this._finish(); 28 }, 29 _finish : function(){ 30 var queue = []; 31 if (this.state == 1) 32 queue = this.doneQueue; 33 else if (this.state == 2) 34 queue = this.failQueue; 35 for (var i = 0, len = queue.length; i < len; i++) { 36 var cb = queue[i]; 37 cb.apply(this, this.args); 38 } 39 return this; 40 } 41 };
demo:
1 function demo( callback ){ 2 var dtd = new Deferred(); 3 setTimeout(function(){ 4 dtd.resolve(); 5 callback(); 6 }, 1 * 1000); 7 return dtd; 8 } 9 10 demo(function(){ 11 alert(22); 12 }).done(function(){ 13 alert(33); 14 });
参考: