`
yuyongkun4519
  • 浏览: 44589 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

jQuery的deferred对象详解

 
阅读更多

今天介绍jQuery1.5.0版本引入的一个新功能--Deferred.
一,什么是Deferred对象?
开发网站中经常有一些耗时操作,这些耗时操作既有异步操作(ajax读取服务器数据),也有同步操作(遍历一些大型数组),通常这些操作不能马上得到结果,我们这时候就会用回调函数(callback),原来jQuery对回调函数方面的功能比较弱,于是有了Deferred。所以说Deferred是jQuery的异步回调解决方案。
二,ajax链式写法
jQuery的ajax操作的传统写法:

$.ajax({
  url: "test.php",
  success: function(){
    alert("哈哈,成功了!");
  },
  error:function(){
    alert("出错啦!");
  }
});

 
在jQuery1.5.0以下版本$.ajax()返回的xhr对象,没有链式写法,jQuery1.5.0以上版本支持链式写法。

 

 

 $.ajax('test.php').done(function() {
     alert('成功');
 }).fail(function() {
     alert('失败');
 });

 
可以看到,done()相当于success方法,fail()相当于error方法。采用链式写法以后,代码的可读性大大提高。

三、为同一操作指定多个回调函数

很简单,还是以上面的代码为例,直接把它加在后面就行了。

 

 $.ajax('test.php').done(function() {
     alert('成功');
 }).fail(function() {
     alert('失败');
 }).done(function(){
     alert('成功2');
 });
 
 
四、为多个操作指定回调函数

deferred对象的另一大好处,就是它允许你为多个事件指定一个回调函数。
$.when($.ajax('test1.php'),$.ajax('test2.php')).done(function() {
   alert('成功');
}).fail(function() {
   alert('失败');
});
 
这段代码的意思是,如果$.ajax('test1.php')和$.ajax('test2.php')都成功了,就执行done()指定的回调函数;如果有一个失败或都失败了,就执行fail()指定的回调函数。
五、普通操作的回调函数接口(上)

deferred对象的最大优点,就是它把这一套回调函数接口,从ajax操作扩展到了所有操作。也就是说,任何一个操作----不管是ajax操作还是本地操作,也不管是异步操作还是同步操作----都可以使用deferred对象的各种方法,指定回调函数。

我们来看一个具体的例子。假定有一个很耗时的操作wait:
  var wait = function() {
        var tasks = function() {
            alert('执行完毕');
        }
        setTimeout(tasks, 3000);
  }
  
如何为它指定回调函数?

可以使用$.when():
$.when(wait()).done(function(){
alert('成功');
}).fail(function(){
alert('失败');
});
   
但是,这样写的话,done()方法会先立即执行,然后等待3s执行tasks函数,这并不是我们要的结果,会有这样结果的原因在于$.when()的参数只能是deferred对象,所以我们要对wait()进行改写:
    var dtd = $.Deferred();//创建一个Deferred对象
    var wait = function(dtd) {
        var tasks = function() {
            alert('执行完毕');
            dtd.resolve();//改变Deferred对象执行状态
        }
        setTimeout(tasks, 3000);
        return dtd;
    }
    $.when(wait(dtd)).done(function() {
        alert('成功');
    }).fail(function() {
        alert('失败');
    });
 
wait()函数运行完,就会自动运行done()方法指定的回调函数。

详解:deferred.resolve()方法和deferred.reject()方法
要理解这两个方法先了解deferred对象的三种执行状态:
1,pending:deferred执行状态未完成
2,resolved:deferred执行状态完成
3,rejected:deferred执行状态失败
执行deferred.resolve()方法,deferred执行状态从未完成变成已完成状态(即:resolved状态),done回调函数执行,执行deferred.reject()方法,deferred执行状态从未完成变成失败状态(即:rejected状态),fail回调函数执行。
 
六、deferred.promise()方法

上面这种写法,由于dtd是一个全局对象,所以它的执行状态可以从外部改变。

请看下面的代码:
 var dtd = $.Deferred(); // 新建一个Deferred对象

  var wait = function(dtd){

    var tasks = function(){

      alert("执行完毕!");

      dtd.resolve(); // 改变Deferred对象的执行状态

    };

    setTimeout(tasks,5000);

    return dtd;

  };

  $.when(wait(dtd))

  .done(function(){ alert("哈哈,成功了!"); })

  .fail(function(){ alert("出错啦!"); });

  dtd.resolve();
 

在代码的尾部加了一行dtd.resolve(),这就改变了dtd对象的执行状态,因此导致done()方法立刻执行,跳出"哈哈,成功了!"的提示框,等5秒之后再跳出"执行完毕!"的提示框。

为了避免这种情况,jQuery提供了deferred.promise()方法。由deferred.promise()方法生成的deferred对象不能改变deferred的执行状态(即不支持deferred.resolve()方法和deferred.reject()方法),但是仍然可以执行done和fail回调函数.
示例:
     var wait = function(dtd) {    
        var dtd = $.Deferred(); //在函数内部,新建一个Deferred对象
        var tasks = function() {      
            alert("执行完毕!");      
            dtd.resolve(); // 改变Deferred对象的执行状态

                
        };

        setTimeout(tasks, 5000);
        return dtd.promise(); // 返回promise对象
    };
      
    $.when(wait()).done(function() {
        alert("哈哈,成功了!");
    }).fail(function() {
        alert("出错啦!");
    });
 
 
七、$.Deferred

另一种防止执行状态被外部改变的方法,是使用deferred对象的构建函数$.Deferred()。

这时,wait函数还是保持不变,我们直接把它传入$.Deferred():
    var awit = function(dtd) {
        var tasks = function() {
            alert('执行完毕');
            dtd.resolve();
        }
        setTimeout(tasks, 3000);
        return dtd.promise();
    }
    $.Deferred(awit).done(function() {
        alert('成功');
    }).fail(function() {
        alert('失败');
    });


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

八、在wait对象上部署deferred接口。
var dtd = $.Deferred();
    var awit = function(dtd) {
        var tasks = function() {
            alert('执行完毕');
            dtd.resolve();
        }
        setTimeout(tasks, 3000);
    }
    dtd.promise(awit);
    awit.done(function() {
        alert('成功');
    }).fail(function() {
        alert('失败');
    }).done(function() {
        alert('成功2');
    });
    awit(dtd);
 

这里的关键是dtd.promise(wait)这一行,它的作用就是在wait对象上部署Deferred接口。正是因为有了这一行,后面才能直接在wait上面调用done()和fail()。

十、小结:deferred对象的方法

前面已经讲到了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("已执行!");} );

 

 

参考文章:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

作者:阮一峰

分享到:
评论

相关推荐

    jQuery的deferred对象使用详解

    jQuery中的deferred对象是自jQuery 1.5.0版本引入的一种新特性,旨在解决JavaScript中异步操作的回调函数管理问题。deferred对象可以看作是一种特殊的对象,它允许你延迟到某个未来时刻执行某项操作。它是jQuery的回...

    jQuery中的deferred对象和extend方法详解

    jQuery中的`deferred对象`和`extend方法`是JavaScript异步编程的重要工具,尤其在处理AJAX请求和其他异步操作时非常有用。`deferred对象`是jQuery 1.5.0版本引入的,它提供了一种更优雅的方式来管理回调函数,解决了...

    jQuery之Deferred对象详解

    jQuery中的Deferred对象是一个非常重要的概念,它用于处理异步操作,并且提供了一种统一的方式来处理这些操作的完成情况。在深入了解Deferred对象之前,我们需要明白什么是Promises以及它们解决了哪些JavaScript编程...

    jQuery.deferred对象使用详解

    jQuery deferred对象是jQuery中一个重要的概念,它在jQuery 1.5版本中引入,用于更有效地处理异步操作。本文将详细介绍jQuery deferred对象的使用方法,并解释其优势。 一、什么是deferred对象? 在jQuery 1.5版本...

    jQuery中deferred对象使用方法详解

    在jquery1.5之后的版本中,加入了一个deferred对象,也就是延迟对象,用来处理未来某一时间点发生的回调函数。同时,还改写了ajax方法,现在的ajax方法返回的是一个deferred对象。 那就来看看deferred对象的用法。 1...

    利用jQuery的deferred对象实现异步按顺序加载JS文件

    前段时间看了阮一峰的jQuery的deferred对象详解一文,对jQuery中的deferred的用法了一些了解,今天看到园子里的一篇文章:关于重构JS前端框架的失败经验(顺便怀念那些死去的代码),于是把我之前写的一个利用jQuery...

    详解jQuery中的deferred对象的使用(一)

    jQuery的`deferred`对象是实现异步操作的一种手段,它是对Promise/A+规范的早期实现。在jQuery 1.5及以后的版本中,`deferred`对象被引入,作为处理异步操作回调的一种更优雅的方式。 `deferred`对象的核心在于它...

    详解JavaScript异步编程中jQuery的promise对象的作用_.docx

    详解JavaScript异步编程中jQuery的promise对象的作用 Promise 对象是 JavaScript 异步编程中的一种重要概念,特别是在 jQuery 库中。Promise 对象的主要作用是解决异步编程中的回调地狱问题,提供了一种简洁的方式...

    Jquery详解-源码分析

    9. **延迟对象(Deferred)**:jQuery引入了 Deferred 对象来处理异步操作,使得回调函数的编写更加清晰和灵活。 10. **性能优化**:jQuery源码中包含了许多性能优化技巧,如缓存查找结果、批量操作和使用`...

    jQuery源码分析之Callbacks详解

    Deferred是jQuery中用于简化异步编程的工具,它通过Callbacks来维护回调函数队列,从而使得复杂的异步流程能以更加直观的方式编写。Queue则是jQuery中处理同步队列的系统,通过Callbacks来驱动动画效果,使得动画的...

    JQuery1.5中文版

    **jQuery 1.5中文版详解** jQuery是一个广泛使用的JavaScript库,它极大地简化了JavaScript的DOM操作、事件处理、动画制作以及Ajax交互。jQuery 1.5是该库的一个重要版本,尤其对于中文用户而言,提供了官方中文版...

Global site tag (gtag.js) - Google Analytics