jQuery - Deferred对象的使用

钮善
2023-12-01

ES6原生提供的Promise对象已成为JavaScript实现异步编程的标准方式,而jQuery提供的Deferred对象,本质上是对Promise的进一步封装和增强。
以下为jQuery对Deferred的官方说明:

As of jQuery 1.5, the Deferred object provides a way to register multiple callbacks into self-managed callback queues, invoke callback queues as appropriate, and relay the success or failure state of any synchronous or asynchronous function.

另外,jQuery也提供了一个Promise对象,但该对象本质是在原来的Deferred对象上返回另一个Deferred对象,后者只开放与改变执行状态无关的方法,屏蔽与改变执行状态有关的方法,从而使得执行状态不能被改变。

This object provides a subset of the methods of the Deferred object (then, done, fail, always, pipe, progress, state and promise) to prevent users from changing the state of the Deferred.

Deferred对象的基本使用

简单说,Deferred对象就是jQuery的回调函数解决方案。
对于耗时很长的操作(既可以是异步操作,也可以是同步操作),都可以使用Deferred对象来进行异步编程。

. D e f e r r e d ( ) 和 .Deferred()和 .Deferred().when()的基本用法,$.when()方法的参数只能是Deferred对象

//新建Deferred对象
var def = $.Deferred();
//需要使用回调函数进行监听的操作,并传入和返回deferred对象
var func = function(def) {
	//do something
	...
	//改变Deferred状态
	def.resolve();
	...
	//返回Deferred对象
	return def;
};
//使用when()监听Deferred状态变化
$.when(func())
  .done(function() {...}) //成功时执行,即状态为resolved
  .fail(function() {...}) //失败时执行,即状态为rejected
  .always(function() {...}); //已完成执行,无论是何种状态

Deferred.promise()的基本用法,避免Deferred对象状态被外部改变

//新建Deferred对象
var def = $.Deferred();
//需要使用回调函数进行监听的操作
var func = function(def) {
	//do something
	...
	//改变Deferred状态
	def.resolve();
	...
	//返回promise对象
	return def.promise();
};
//改为对返回的Promise()对象进行操作
var d = func(def);
$.when(d)
  .done(function() {...}) //成功时执行,即状态为resolved
  .fail(function() {...}) //失败时执行,即状态为rejected
  .always(function() {...}); //已完成执行,无论是何种状态

//外部改变Deferred状态,但此种情况下是无效的
d.resolve();

由此可见,jQuery提供的Promise对象可以看做是Deferred对象的特例,与ES6原生提供的Promise对象所具有的意义并不相同。
为了避免Deferred状态被外部改变,更好的做法是把新建Deferred对象的语句放到操作函数内部,即避免把Deferred作为一个全局对象。

为同一个操作指定多个回调函数,它们按照添加顺序执行。

$.when(func())
  .done(function() {//do something ...})
  .done(function() {//do otherthing  ...})
  ...

为多个操作指定同一个回调函数,如果都成功了,就执行done()指定的回调函数,只要有一个失败了,就执行fail()指定的回调函数。

$.when(func1(), func2())
  .done(function() {...})
  .fail(function() {...});

Deferred对象在Ajax中的运用

从jQuery 1.5开始,$.ajax()返回的便不再是XMLHttpRequest对象,而是Deferred对象,因此可以进行链式操作,并支持执行多个回调。甚至可以在请求完成后,仍然可以注册回调函数。
另外,在Ajax操作中,Deferred会根据返回对象,自动改变自身的执行状态。

//1.5版本之前的写法
$.ajax({
	url: '...',
	success: function() {...},
	error: function() {...},
	complete: function() {}
});

//1.5版本之后的写法
var def = $.ajax(...)
  .done(function() {...})
  .fail(function() {...})
  .always(function() {...});
 
 def.always(function() {
	//另一个回调函数
});

Deferred对象常用方法总结

  1. $.Deferred() 生成一个deferred对象;
  2. $.when() 为若干个操作指定回调函数
  3. deferred.done() 指定操作成功时的回调函数
  4. deferred.fail() 指定操作失败时的回调函数
  5. deferred.then() 成功done()和失败fail()的合并写法
  6. deferred.always() 完成时的回调函数,无论状态如何总是执行
  7. deferred.progress() 指定在deferred生成进度通知时的回调函数
  8. deferred.resolve() 改变deferred状态为“已完成”,从而触发done()方法
  9. deferred.reject() 改变deferred状态为“已失败”,从而触发fail()方法
  10. deferred.promise() 没有参数时,返回一个Promise对象;有参数时,作用为在参数对象上部署deferred接口。

更多jQuery.Deferred对象的用法,可参考官方文档:http://api.jquery.com/jQuery.Deferred/

 类似资料: