jQuery - Deferred 对象使用


阅读了阮一峰老师的jQuery的deferred对象详解,自己整理一下。


0. jQuery Deferred对象背景


随着WEB单页应用的普及,现在越来越多的页面逻辑已经交由JS代码来处理,其中难免有向后台请求资源等费时操作。

由于浏览器是单线程执行JS代码, 所以为了防止在请求的同时页面出现卡死的现象,提出了异步请求(ajax)。

我们可以将渲染返回数据的操作在异步请求的回调中执行, 避免页面卡死。

jQuery的ajax方法最典型的回调方法就是success和error,已经相当常用了。

而Deferred对象提供了更方便更强大的方法控制回调的逻辑, Deferred对象是早在jQuery1.5版本时就引入的特性(2011年),支持jQuery的链式调用语法。


1. 什么是Deferred对象?


简单理解就是: Deferred的实例可以注册多个callback函数到一个队列中去,并根据Deferred实例的状态来有选择的,顺序的执行这些回调函数。

可以通过调用jQuery.Deferred()方法来获得一个Deferred Object实例。

var d = jQuery.Deferred() // create Deferred Object

Deferred对象有三种执行状态:

1. pending

2. resolved

3. rejected

可以在Deferred对象上调用state()方法获取。

三种状态代表的含义见名知意。


2. 主要方法: resolve(), reject()


deferred.resolve()

创建一个Deferred对象,Deferred对象默认执行状态为“pending‘”,
延迟一小段时间模拟异步操作过程,异步操作完成后,在Deferred对象上调用resolve()方法, 
Deferred对象执行状态变为“resolved”
  var d = jQuery.Deferred() // create Deferred Object
  console.log(d.state()); // return 'pending'
  function executeTasks() { 
    var _tasks = function() { 
    
    // 'finish tasks here'
    d.resolve(); // notify Deferred Object has been resolved
    console.log(d.state()); // return 'resolved' 
    } 
    setTimeout(_tasks, 3000); 
   }
  executeTasks();

deferred.reject()

如果异步操作过程失败,可以在Deferred对象上调用reject()方法,
Deferred对象执行状态变为“rejected”.
  var d = jQuery.Deferred() // create Deferred Object


  function executeTasks() {
    var _tasks = function() {

      // 'finish tasks here'

      d.reject(); // notify Deferred Object has been rejected
      console.log(d.state());  // return 'rejected'
    }
    setTimeout(_tasks, 3000);
  }
  executeTasks();


3. 主要事件: done(), fail(), always()

deferred.done()

Deferred对象获得状态“resolved”后,执行done()回调。
可以自由添加多个done回调函数,如下。
  var d = jQuery.Deferred() // create Deferred Object
  d.done(function(){
    console.log('I am done. n.n'); // 1
  }).done(function(){
    console.log('I am done again. n.n'); // 2
  })

  function executeTasks() {
    var _tasks = function() {
      
      // 'finish tasks here'

      d.resolve(); // notify Deferred Object has been resolved
    }
    setTimeout(_tasks, 3000);
  }

  executeTasks();

deferred.fail()

Deferred对象获得状态“rejected”后,执行fail()回调。
因为Deferred对象支持链式调用,所以可以直接在注册done回调之后直接注册fail()回调。
  var d = jQuery.Deferred() // create Deferred Object
  d.done(function(){
    console.log('I am done. n.n'); // 1
  }).done(function(){
    console.log('I am done again. n.n'); // 2
  }).fail(function(){
    console.log('I am rejected. >.<');
  })

  function executeTasks() {
    var _tasks = function() {
      
      // 'finish tasks here'

      d.reject(); // notify Deferred Object has been rejected
    }
    setTimeout(_tasks, 3000);
  }

  executeTasks();


deferred.always()

always函数顾名思义,无论Deferred对象最终获得resolved状态还是rejected状态,该回调函数总是会被调用。

  var d = jQuery.Deferred() // create Deferred Object
  d.fail(function(){
    console.log('I am rejected. >.<');
  }).always(function(){
    console.log('I am always here. =.= ');
  });

  function executeTasks() {
    var _tasks = function() {

      // 'finish tasks here'

      d.reject(); // notify Deferred Object has been rejected
      d.state();  // return 'rejected'
    }
    setTimeout(_tasks, 3000);
  }
  executeTasks();


4. 为多个操作指定回调函数


$.when()

when()方法使得Deferred对象支持多个异步操作都完成后,才执行统一定义的回调。

var d1 = $.Deferred();
var d2 = $.Deferred();
var d3 = $.Deferred();

$.when( d1, d2, d3 ).done(function ( v1, v2, v3 ) {
    console.log( v1 ); // v1 is undefined
    console.log( v2 ); // v2 is "abc"
    console.log( v3 ); // v3 is an array [ 1, 2, 3, 4, 5 ]
});

d1.resolve();
d2.resolve( "abc" );
d3.resolve( 1, 2, 3, 4, 5 );

假若所有Deferred对象获得resolved状态,执行done回调。

假若其中至少一个Deferred对象获得rejected状态,执行fail回调。


5. Defferred和promise()


deferred.promise()

promise()方法返回一个和原Deferred对象几乎相同的代理对象,
只不过该代理对象只允许attach事件如done, fail和always,
但不允许调用改变执行状态的方法如resolve和reject。
function getPromise() {
    return $.Deferred().promise();
}

try {
    getPromise().resolve("a");
} catch(err){
    console.log(err);
}
最常用的应用是jQuery的ajax方法,该方法返回的就是一个Deferred对象的Promise()对象。
$.ajax("/home/news/")
.done(function(){ alert('I am done. n.n');} )
.fail(function(){ alert('I am rejected. >.<'); } )
这样做的好处是避免在Deferred对象的创建者的作用范围外改变Deferred对象的执行状态。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
jQuery 中的 Deferred 对象提供了一种优雅的方式来处理异步操作,它可以让我们更方便地控制异步操作的状态和执行顺序。下面是 Deferred 对象的常用方法: 1. $.Deferred():创建一个 Deferred 对象。 2. deferred.done():当 Deferred 对象的状态变为已完成时,调用该方法注册的回调函数。 3. deferred.fail():当 Deferred 对象的状态变为已失败时,调用该方法注册的回调函数。 4. deferred.always():无论 Deferred 对象的状态是已完成还是已失败,都调用该方法注册的回调函数。 5. deferred.then():当 Deferred 对象的状态变化时,调用该方法注册的回调函数。它可以接受两个参数,第一个参数是已完成状态的回调函数,第二个参数是已失败状态的回调函数。 6. deferred.promise():返回一个 Promise 对象,该对象可以被传递给其他函数或者方法,但只能调用 then()、catch() 和 finally() 方法,不能改变 Deferred 对象的状态。 下面是一个使用 Deferred 对象的示例代码: ```javascript function asyncAction() { var defer = $.Deferred(); setTimeout(function() { defer.resolve("Async Action Completed!"); }, 2000); return defer.promise(); } var promise = asyncAction(); promise.then(function(data) { console.log(data); }).fail(function() { console.log("Async Action Failed!"); }).always(function() { console.log("Async Action Done!"); }); ``` 在这个例子中,我们定义了一个 asyncAction() 函数,它返回一个 Deferred 对象。在该函数内部,我们使用 setTimeout() 函数模拟一个异步操作,并在两秒后调用 resolve() 方法,将 Deferred 对象的状态设置为已完成。然后我们使用 promise 变量保存该 Deferred 对象的 Promise 对象,并使用 then()、fail() 和 always() 方法注册回调函数。在 then() 方法中,输出异步操作完成的信息;在 fail() 方法中,输出异步操作失败的信息;在 always() 方法中,输出异步操作完成的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值