全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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

1 deferred对象

deferred对象是jQuery的回调函数解决方案,它是从jQuery1.5.0版本开始引入的功能

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)ajax操作的链式写法

先回顾一下jQuery的ajax操作的传统写法:

$.ajax({

    url: "test.html",

    success: function(){
      alert("哈哈,成功了!");
    },

    error:function(){
      alert("出错啦!");
    }
  });

在上面的代码中,$.ajax()接受一个对象参数,这个对象包含两个方法:success方法指定操作成功后的回调函数,error方法指定操作失败后的回调函数。

$.ajax()操作完成后,如果使用的是低于1.5.0版本的jQuery,返回的是XHR对象,你没法进行链式操作;如果高于1.5.0版本,返回的是deferred对象,可以进行链式操作。

有了deferred对象之后,可以这样写了

$.ajax("test.html")

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

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

2)指定同一操作的多个回调函数

deferred对象的一大好处,就是它允许你自由添加多个回调函数。

还是以上面的代码为例,如果ajax操作成功后,除了原来的回调函数,我还想再运行一个回调函数,怎么办?

很简单,直接把它加在后面就行了。

$.ajax("test.html")

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

  .fail(function(){ alert("出错啦!"); } )
  .done(function(){ alert("第二个回调函数!");} );

回调函数可以添加任意多个,它们按照添加顺序执行。

3)为多个操作指定回调函数

deferred对象的另一大好处,就是它允许你为多个事件指定一个回调函数,这是传统写法做不到的。

请看下面的代码,它用到了一个新的方法$.when():

$.when($.ajax("test1.html"), $.ajax("test2.html"))

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

这段代码的意思是,先执行两个操作$.ajax("test1.html")和$.ajax("test2.html"),如果都成功了,就运行done()指定的回调函数;如果有一个失败或都失败了,就执行fail()指定的回调函数。

4)普通操作的回调函数接口(上)

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

我们来看一个具体的例子。假定有一个很耗时的操作wait:

var wait = function(){

    var tasks = function(){

      alert("执行完毕!");

    };

    setTimeout(tasks,5000);
  };

我们为它指定回调函数,应该怎么做呢?

很自然的,你会想到,可以使用$.when():

$.when(wait())

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

但是,这样写的话,done()方法会立即执行,起不到回调函数的作用。原因在于$.when()的参数只能是deferred对象,所以必须对wait()进行改写:

var dtd = $.Deferred(); // 新建一个deferred对象

  var wait = function(dtd){

    var tasks = function(){

      alert("执行完毕!");

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

    };

    setTimeout(tasks,5000);

    return dtd;
  };

现在,wait()函数返回的是deferred对象,这就可以加上链式操作了。

$.when(wait(dtd))

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

wait()函数运行完,就会自动运行done()方法指定的回调函数。

5)deferred.resolve()方法和deferred.reject()方法 

jQuery规定,deferred对象有三种执行状态----未完成,已完成和已失败。如果执行状态是"已完成"(resolved),deferred对象立刻调用done()方法指定的回调函数;如果执行状态是"已失败",调用fail()方法指定的回调函数;如果执行状态是"未完成",则继

续等待,或者调用progress()方法指定的回调函数(jQuery1.7版本添加)。

前面部分的ajax操作时,deferred对象会根据返回结果,自动改变自身的执行状态;但是,在wait()函数中,这个执行状态必须由程序员手动指定。dtd.resolve()的意思是,将dtd对象的执行状态从"未完成"改为"已完成",从而触发done()方法。

类似的,还存在一个deferred.reject()方法,作用是将dtd对象的执行状态从"未完成"改为"已失败",从而触发fail()方法。

var dtd = $.Deferred(); // 新建一个Deferred对象

  var wait = function(dtd){

    var tasks = function(){

      alert("执行完毕!");

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

    };

    setTimeout(tasks,5000);

    return dtd;

  };

  $.when(wait(dtd))

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

6)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对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和

reject()方法),从而使得执行状态不能被改变。

请看下面的代码:

var dtd = $.Deferred(); // 新建一个Deferred对象

  var wait = function(dtd){

    var tasks = function(){

      alert("执行完毕!");

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

    };

    setTimeout(tasks,5000);

    return dtd.promise(); // 返回promise对象

  };

  var d = wait(dtd); // 新建一个d对象,改为对这个对象进行操作

  $.when(d)

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

  .fail(function(){ alert("出错啦!"); });
  d.resolve(); // 此时,这个语句是无效的

在上面的这段代码中,wait()函数返回的是promise对象。然后,我们把回调函数绑定在这个对象上面,而不是原来的deferred对象上面。这样的好处是,无法改变这个对象的执行状态,要想改变执行状态,只能操作原来的deferred对象。

不过,更好的写法是将dtd对象变成wait()函数的内部对象。

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("出错啦!"); });

7)普通操作的回调函数接口(中)

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

这时,wait函数还是保持不变,我们直接把它传入$.Deferred():

$.Deferred(wait)
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });

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

8)普通操作的回调函数接口(下)

除了上面两种方法以外,我们还可以直接在wait对象上部署deferred接口。

var dtd = $.Deferred(); // 生成Deferred对象

  var wait = function(dtd){

    var tasks = function(){

      alert("执行完毕!");

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

    };

    setTimeout(tasks,5000);

  };

  dtd.promise(wait);

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

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

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

2 extend方法

JQuery的extend扩展方法:

Jquery的扩展方法extend是我们在写插件的过程中常用的方法,该方法有一些重载原型,在此,我们一起去了解了解。

1)Jquery的扩展方法原型是:   

extend(dest,src1,src2,src3...);

它的含义是将src1,src2,src3...合并到dest中,返回值为合并后的dest,由此可以看出该方法合并后,是修改了dest的结构的。如果想要得到合并的结果却又不想修改dest的结构,可以如下使用:

var newSrc=$.extend({},src1,src2,src3...)//也就是将"{}"作为dest参数。

这样就可以将src1,src2,src3...进行合并,然后将合并结果返回给newSrc了。如下例:

var result=$.extend({},{name:"Tom",age:21},{name:"Jerry",sex:"Boy"})

那么合并后的结果

result={name:"Jerry",age:21,sex:"Boy"}

也就是说后面的参数如果和前面的参数存在相同的名称,那么后面的会覆盖前面的参数值。

2)省略dest参数

上述的extend方法原型中的dest参数是可以省略的,如果省略了,则该方法就只能有一个src参数,而且是将该src合并到调用extend方法的对象中去,如:

$.extend(src)

该方法就是将src合并到jquery的全局对象中去,如:

$.extend({
hello:function(){alert('hello');}
});

就是将hello方法合并到jquery的全局对象中。

$.fn.extend(src)

该方法将src合并到jquery的实例对象中去,如:

$.fn.extend({
hello:function(){alert('hello');}
});

就是将hello方法合并到jquery的实例对象中。

下面例举几个常用的扩展实例:

$.extend({net:{}});

这是在jquery全局对象中扩展一个net命名空间。

$.extend($.net,{
hello:function(){alert('hello');}
})

这是将hello方法扩展到之前扩展的Jquery的net命名空间中去。

3)Jquery的extend方法还有一个重载原型: 

extend(boolean,dest,src1,src2,src3...)

第一个参数boolean代表是否进行深度拷贝,其余参数和前面介绍的一致,什么叫深层拷贝,我们看一个例子:

var result=$.extend( true, {}, 
{ name: "John", location: {city: "Boston",county:"USA"} }, 
{ last: "Resig", location: {state: "MA",county:"China"} } );

我们可以看出src1中嵌套子对象location:{city:"Boston"},src2中也嵌套子对象location:{state:"MA"},第一个深度拷贝参数为true,那么合并后的结果就是:

result={name:"John",last:"Resig",
location:{city:"Boston",state:"MA",county:"China"}} 

也就是说它会将src中的嵌套子对象也进行合并,而如果第一个参数boolean为false,我们看看合并的结果是什么,如下:

var result=$.extend( false, {}, 
{ name: "John", location:{city: "Boston",county:"USA"} }, 
{ last: "Resig", location: {state: "MA",county:"China"} } 
);

那么合并后的结果就是:

result={name:"John",last:"Resig",location:{state:"MA",county:"China"}}

以上是网上看到的两篇分别对jQuery中的deferred对象和extend方法的介绍,感觉比较详细而且容易理解,所以把它们整理到一起与大家分享!

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


# jquery  # deferred对象  # extend方法  # jQuery的deferred对象使用详解  # jQuery Deferred和Promise创建响应式应用程序详细介绍  # 利用jQuery的deferred对象实现异步按顺序加载JS文件  # jQuery之Deferred对象详解  # jQuery源码分析-05异步队列 Deferred 使用介绍  # jQuery $.extend()用法总结  # jQuery插件开发的两种方法及$.fn.extend的详解  # jQuery.extend 函数详解  # 原生js实现复制对象、扩展对象 类似jquery中的extend()方法  # jQuery.extend()的实现方式详解及实例  # 回调  # 链式  # 的是  # 多个  # 第一个  # 新建一个  # 这是  # 并到  # 中去  # 未完成  # 有一个  # 象中  # 把它  # 这段  # 这就  # 运行状态  # 第二个  # 可以使用  # 在上面  # 这一行 


相关文章: 微信小程序 五星评分(包括半颗星评分)实例代码  C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)  已有域名如何免费搭建网站?  网站制作新手教程,新手建设一个网站需要注意些什么?  自助网站制作软件,个人如何自助建网站?  平台云上自主建站:模板化设计与智能工具打造高效网站  昆明高端网站制作公司,昆明公租房申请网上登录入口?  网站制作软件免费下载安装,有哪些免费下载的软件网站?  青岛网站建设如何选择本地服务器?  建站之星CMS建站配置指南:模板选择与SEO优化技巧  建站之星24小时客服电话如何获取?  如何用5美元大硬盘VPS安全高效搭建个人网站?  已有域名和空间,如何快速搭建网站?  宿州网站制作公司兴策,安徽省低保查询网站?  详解jQuery停止动画——stop()方法的使用  网站制作服务平台,有什么网站可以发布本地服务信息?  制作网站公司那家好,网络公司是做什么的?  如何快速搭建高效香港服务器网站?  微信推文制作网站有哪些,怎么做微信推文,急?  怀化网站制作公司,怀化新生儿上户网上办理流程?  网站制作多少钱一个,建一个论坛网站大约需要多少钱?  小型网站建站如何选择虚拟主机?  广州网站设计制作一条龙,广州巨网网络科技有限公司是干什么的?  如何通过PHP快速构建高效问答网站功能?  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  如何在西部数码注册域名并快速搭建网站?  如何选择高效稳定的ISP建站解决方案?  公司门户网站制作流程,华为官网怎么做?  ,如何利用word制作宣传手册?  简历在线制作网站免费,免费下载个人简历的网站是哪些?  ,网页ppt怎么弄成自己的ppt?  高性能网站服务器配置指南:安全稳定与高效建站核心方案  官网自助建站系统:SEO优化+多语言支持,快速搭建专业网站  如何获取上海专业网站定制建站电话?  如何在腾讯云免费申请建站?  如何选择适配移动端的WAP自助建站平台?  定制建站流程步骤详解:一站式方案设计与开发指南  音乐网站服务器如何优化API响应速度?  高防服务器租用首荐平台,企业级优惠套餐快速部署  开源网站制作软件,开源网站什么意思?  建站168自助建站系统:快速模板定制与SEO优化指南  如何在IIS中新建站点并配置端口与物理路径?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  电影网站制作价格表,那些提供免费电影的网站,他们是怎么盈利的?  常州企业建站如何选择最佳模板?  广东专业制作网站有哪些,广东省能源集团有限公司官网?  公司网站制作费用多少,为公司建立一个网站需要哪些费用?  如何通过VPS建站实现广告与增值服务盈利?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  弹幕视频网站制作教程下载,弹幕视频网站是什么意思? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。