jQuery.Deferred(func)总结

Deferred异步队列的总结:

jQuery.Deferred(func) {

(1)创建成功、失败、消息回调函数列表,设置初始状态为pending

var doneList = jQuery.Callbacks('once memory'),
	    failList = jQuery.Callbacks('once memory'),
	    progressList = jQuery.Callbacks('once memory'),
	    state = 'pending',
	    lists = {
	         resolve: doneList,
		 reject: failList,
		 notify: progressList
	    },

	promise = {
	     done:doneList.add,
	     fail:failList.add,
              progress: progressList.add
	}
	//方法deferred.done(), deferred.fail(), deferred.progress()分别用于添加成功回调函数,失败回调函数,消息回调函数到
	对应的函数列表中。

	//添加触发成功、失败、消息回调函数列表的方法
	for(key in lists) {
	     deferred[key] = lists[key].fire;
	     deferred[key + 'With'] = lists[key].fireWith;
	}
	//这里变量lists可以减少实现的代码行数,是值得学习的技巧

	//便捷方法deferred.then(doneCallbacks, failCallbacks, progressCallbacks)用于同时添加成功回调函数,失败回调函数和消息
	回调函数到对应的回调函数列表中
	then: function(doneCallbacks, failCallbacks, progressCallbacks) {
	      deferred.done(doneCallbacks).fail(failCallbacks).progress(progressCallbacks);
	      return  this;
	}

	always: function() {
	    deferred.done.apply(deferred, arguments).fail.apply(deferred, arguments);
	    return this;
	}
}

(2)创建异步队列的只读副本

deferred.promise()用于返回当前异步队列的只读副本,或为一个普通的javascript对象增加只读副本中的方法并返回。

只读副本只暴露了添加回调函数和判断状态的方法:
  done(),fail(),progress(), then(),always(),state(),pipe()。

不包含触发执行和改变状态的方法:
  resolve(),reject(),notify(),resolveWith(),rejectWith(),notifyWith()。

(3)创建异步队列

deferred = promise.promise({}),
   key;
   for(key in lists) {
        deferred[key] = lists[key].fire;
	deferred[key + 'With'] = lists[key].fireWith;
   }

   deferred.done(function() {
      state = 'resolved';
   }, failList.disabled, progressList.lock).fail(function() {
      state = 'rejected';
   },doneList.disabled, progressList.lock);

(4)如果传入了函数参数func,则调用

if(func) {
        func.call(deferred, deferred);
    }

jQuery规定,$.Deferred()可以接受一个函数名(注意,是函数名)作为参数,$.Deferred所生成的deferred
    对象将作为这个函数的默认参数。

(5)返回异步队列 deferred;
 例如1:

$.fn.animatePromise = function(prop, speed,callback) {
       var element = this;
	return $.Deferred(function(dtd) {
	     element.animate(prop, speed, function() {
	          dtd.resolve();
		  if(callback) {
		       callback.apply(this, arguments);
		  }
	      });
	}).promise();
}

我的理解:先创建Deferred对象,然后执行里面传入的函数。然后可以使用$.when()同步化不同的动画

var fadeDiv1Out = $('.div1').animatePromise({opacity:0},5000, function() {
	alert('before or after');
}),
fadeDiv2In = $('.div2').animatePromise({opacity:0},1000, function() {
	alert('which is first');
});
			
$.when(fadeDiv2In,fadeDiv1Out).done(function() {
	alert('both animate finished');
});
			
在when中有下列的源码
if(length > 1) {
    for(;i < length; i++) {
       if(arguments[1] && args[i].promise && jQuery.isFunction(args[i].promise)) {
	  <span style="color:#ff0000;">args[i].promise().then(resolveFun(i), deferred.reject, progressFunc(i));</span>
      } else {
	--count;
      }
    }
 }
resolveFunc()称为成功状态监听函数,,在成功状态监听函数中,当子异步队列的方法resolve()或者resolveWith()被调用进入成功状态时,都把成功参数放入数组args中的对应位置, 并使计数器的count减一


上面的方法还可以扩展如下:

$.each(["slideDown", "slideUp", "slideToggle", "fadeIn", "fadeOut", "fadeToggle"], function(index, item){
			$.fn[item + 'promise'] = function(prop, speed, callback) {
				var element = this;
					return $.Deferred(function(dtd) {
						element[name](prop, speed, function() {
							dtd.resolve();
							if(callback) {
								callback.apply(this, arguments);
							}
						});
					}).promise();
				}
			}
		})

例如2:

$.ajax("test.html")
  .done(function(){ alert("哈哈,成功了!");} )
  .fail(function(){ alert("出错啦!"); } )
  .done(function(){ alert("第二个回调函数!");} );
ajax操作时,deferred对象会根据返回结果,自动改变自身的执行状态;但是在其他普通函数中,这个执行状态必须由程序员手动指定。
即需要如上例子中的,dtd.resolve();

例如3:

function readData(){
    $.ajax({ url:"test", dataType:"json" })
    .done(function() {
        //....
    });
}
readData();
//...这里想添加一些后续处理,但程序将在Ajax回调前执行,所以无法达到预期目的

正确的代码:
function readData(){
    return $.ajax({ url:"test", dataType:"json" })
    .done(function() {
        //....
    });
}
readData().done(function () {
    //...想添加的后续处理可以加在这里处理
});

因为是异步调用,所以$.ajax函数的返回值不代表返回结果,只是一个Deferred对象。
如果一个函数包含Ajax调用,那个这个函数必须将Ajax返回的异步对象作为自己的返回值,否则函数的调用者
无法保证后续代码的正常执行顺序。


参考文章:

http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html
http://ju.outofmemory.cn/entry/55151
http://www.cnblogs.com/lhb25/archive/2013/03/05/jquery-deferred-promise.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值