Deferred是jquery的promise接口的实现。他是非同步操作的通用接口,可以看作是完成一个任务之后再执行另外一个任务。

观察者模式是开发中经常使用的模式,这个模式由两个主要部分组成:主题和观察者。通过观察者模式,实现主题和观察者的解耦.

主题负责发布内容,而观察者则接收主题发布的内容。

在 jQuery 中,实现观察者模式的就是 Deferred 了,我们先看它的使用。

使用 Deferred

  1. // 定义主题
  2. var subject = (function(){
  3. var dfd = $.Deferred();
  4.  
  5. var task = function()
  6. {
  7. // 发布内容
  8. dfd.resolve("Alice");
  9. }
  10.  
  11. setTimeout( task, 3000);
  12.  
  13. return dfd.promise();
  14. })();
  15.  
  16. // 两个观察者
  17. var fn1 = function(content){
  18. console.log("fn1: " + content );
  19. }
  20.  
  21. var fn2 = function(content){
  22. console.log("fn2: " + content );
  23. }
  24.  
  25. // 注册观察者
  26. $.when( subject )
  27. .done( fn1 )
  28. .done( fn2 );

在 jQuery 中,甚至可以提供两个主题同时被观察, 需要注意的是,要等两个主题都触发之后,才会真正触发,每个观察者一次得到这两个主题,所以参数变成了 2 个。

  1. // 定义主题
  2. var subjectAlice = (function(){
  3. var dfd = $.Deferred();
  4.  
  5. var task = function()
  6. {
  7. // 发布内容
  8. dfd.resolve("Alice");
  9. }
  10.  
  11. setTimeout( task, 3000);
  12.  
  13. return dfd.promise();
  14. })();
  15.  
  16. var subjectTom = (function(){
  17. var dfd = $.Deferred();
  18.  
  19. var task = function()
  20. {
  21. // 发布内容
  22. dfd.resolve("Tom");
  23. }
  24.  
  25. setTimeout( task, 1000);
  26.  
  27. return dfd.promise();
  28. })();
  29.  
  30. // 两个观察者
  31. var fn1 = function(content1, content2){
  32. console.log("fn1: " + content1 );
  33. console.log("fn1: " + content2 );
  34. }
  35.  
  36. var fn2 = function(content1, content2){
  37. console.log("fn2: " + content1 );
  38. console.log("fn2: " + content2 );
  39. }
  40.  
  41. // 注册观察者
  42. $.when( subjectAlice, subjectTom )
  43. .done( fn1 )
  44. .done( fn2 );

$.when()方法

$.when()接受多个deferred对象作为参数,当它们全部运行成功后,才调用resolved状态的回调函数,但只要其中有一个失败,就调用rejected状态的回调函数。它相当于将多个非同步操作,合并成一个。

例如:

  1. $.when(
  2. $.ajax( "/main.php" ),
  3. $.ajax( "/modules.php" ),
  4. $.ajax( "/lists.php" )
  5. ).then(successFunc, failureFunc);

上面代码表示,要等到三个ajax操作都结束以后,才执行then方法指定的回调函数。

when方法里面要执行多少个操作,回调函数就有多少个参数,对应前面每一个操作的返回结果。

例如:

  1. $.when(
  2. $.ajax( "/main.php" ),
  3. $.ajax( "/modules.php" ),
  4. $.ajax( "/lists.php" )
  5. ).then(function (resp1, resp2, resp3){
  6. console.log(resp1);
  7. console.log(resp2);
  8. console.log(resp3);
  9. });

上面代码的回调函数有三个参数,resp1、resp2和resp3,依次对应前面三个ajax操作的返回结果。

then()方法

then()的作用也是指定回调函数,它可以接受三个参数,也就是三个回调函数。第一个参数是resolve时调用的回调函数,第二个参数是reject时调用的回调函数,第三个参数是progress()方法调用的回调函数。

代码如下:
  1. deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

then()和done()的区别

在jQuery 1.8之后,then()返回一个新的deferred对象,而done()返回的是原有的deferred对象。

如果then()指定的回调函数有返回值,该返回值会作为参数,传入后面的回调函数。

例如:如下代码:

  1. var defer = jQuery.Deferred();
  2. defer.done(function(a,b){
  3. return a * b;
  4. }).done(function( result ) {
  5. console.log("result = " + result);
  6. }).then(function( a, b ) {
  7. return a * b;
  8. }).done(function( result ) {
  9. console.log("result = " + result);
  10. }).then(function( a, b ) {
  11. return a * b;
  12. }).done(function( result ) {
  13. console.log("result = " + result);
  14. });
  15. defer.resolve( 2, 3 );

返回的结果为:

result = 2 
result = 6 
result = NaN

分析:

  1. 1)上面的第一个result是第一个result的最后一个done()的输出,前一个donereturn不会传递到这里,所以resultresolve的第一个参数
    2)第二个result是第二个deferred的输出,第一个then所带的function的输入,传入第二个deferred,因此第五个done能够接受到2*3result
    3)第三个result是第三个deferred的输出,第二个then执行时,只有a,没有b(上一个then执行时返回的是a*b,所以再第三个then执行时只有a,没有b),所以resultNaN
  2.  
  3. 综合例子如下:
  1. var requestInfo = function() {
  2. var defered = $.Deferred();
  3. var url = "https://api.ffan.com/activity/v1/homepage/index";
  4. $.ajax(url, {
  5. dataType: "jsonp",
  6. jsonp: "callback",
  7. timeout: 5000,
  8. data: {
  9. type: "cityList"
  10. }
  11. }).then(function(response) {
  12. if (response && response.data && response.data[0]) {
  13. defered.resolve(response.data[0].cityList);
  14. }
  15. })
  16. return defered.promise();
  17. }
  1. var cityInfo = function(result) {
  2. var list = _.groupBy(result, function(city) {
  3. return city.cityPinYin.charAt(0).toUpperCase();
  4. });
  5.  
  6. _.each(list,function(city,key){
  7. console.log(key);
  8. _.each(city,function(item,index){
  9. console.log("item.cityId="+item.cityId);
  10. console.log("item.cityName="+item.cityName);
  11. })
  12. })
  13.  
  14. //获取第一条数据的cityId
  15. var cityId=list["A"][0].cityId;

  16. //返回值,供下一个then调用
  17. return {
  18. id:cityId
  19. }
  20. }
  1. var info=function(result){
  2. var id=result.id;//上一个then返回的值
  3. console.log("cityid="+id);
  4. return true;
  5. }

调用:

  1. $.when(requestInfo())
  2. .then(cityInfo)
  3. .then(info);

jquery 之 Deferred 使用的更多相关文章

  1. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

  2. jQuery的deferred对象详解

    jQuery的deferred对象详解请猛击下面的链接 http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_ ...

  3. jQuery的deferred对象学习

    #copy { background-color: lightgreen; padding: 15px; margin: 10px } 一.deferred对象简介 deferred对象是jquery ...

  4. jquery 之 Deferred 使用与实现

    观察者模式是开发中经常使用的模式,这个模式由两个主要部分组成:主题和观察者.通过观察者模式,实现主题和观察者的解耦. 主题负责发布内容,而观察者则接收主题发布的内容.通常情况下,观察者都是多个,所以, ...

  5. jQuery的deferred对象详解(转载)

    本文转载自: jQuery的deferred对象详解(转载)

  6. jQuery的Deferred

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  7. jQuery的deferred对象

    应用场景:处理异步任务 看到一篇阮一峰老师的博客挺好的讲的就是jQuery的deferred对象.坦诚讲之前没有怎么用过这个东东呢. 摘其中几点记录下 (1) $.Deferred() 生成一个def ...

  8. jQuery的deferred对象详解(一)

    最近一段时间,都在研究jquery里面的$.Deffered对象,几天都搞不明白,其中源码的运行机制,网上查找了相关的资料,<jQuery的deferred对象详解>阮一峰老师的文章,里面 ...

  9. jQuery的deferred对象解析

    参考: jQuery的deferred对象详解:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_defe ...

  10. [转] jQuery的deferred对象详解

    jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. ...

随机推荐

  1. html5 上传头像示例及其注意事项

    转自[B5教程网]:http://www.bcty365.com/content-142-5244-1.html 这次分享一个简易的上传头像示例,其大致流程为: 一.将选择的图片转为base64字符串 ...

  2. KVC示例

    KVC –key value Coding,可以让我们通过键值编码的形式进行属性值的赋值 参考苹果官网的图.. 1.KVC 定义一个Person类 .h文件 1: #import <Founda ...

  3. C#中的自定义控件中的属性、事件及一些相关特性的总结(转)

      摘要: C#中的自定义控件中的属性(Property).事件(Event)及一些相关特性(Attribute)的总结 今天学习了下C#用户控件开发添加自定义属性的事件,主要参考了MSDN,总结并实 ...

  4. 洛谷 P4109 [HEOI2015]定价

    洛谷 这是今天的考试题,我来发一波- 看L和R的范围,显然不能一个一个加,这样会有很多重复情况,会超时,只要看该数有多少个后导0,就把L加上10的多少次方. 很容易可以想到价格后面尽可能多0, 在此基 ...

  5. while循环。for循环

    1.while循环 基本循环格式 while 条件 : # 循环体 # 如果条件为真,那么循环体则执行 # 如果条件为假,那么循环体不执行 break:退出本层循环. continue:退出本次循环, ...

  6. MySql存储过程、函数

    存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...

  7. 安装MYSQL时出现libaio.so.1 is needed by MySQL-server-5.5,49.1等等

    安装MYSQL是出现: warning: MySQL-server--.linux2..i386.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: ...

  8. Multi-thread & Multi-process

    关于多进程和多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”. 对于到底是使用多进程还是多线程, 要根据实际情况来判断,选择更适合的. 具体情况,可以参考下面: ...

  9. 第二篇 Python图片处理模块PIL(pillow)

    本篇包含:16.Point    17.Putalpha    18.Putdata    19.Putpalette    20.Putpixel      21.Quantize     22.R ...

  10. android开发之网络棋牌类在线游戏开发心得(服务器端、Java) 好文章值得收藏

    标签: android服务器 2013-10-09 17:28 3618人阅读 评论(0) 收藏 举报 分类: android(11) 转自:http://blog.csdn.net/bromon/a ...