jQuery使用():Deferred有状态的回调列表(含源码)

  • deferred的功能及其使用
  • deferred的实现原理及模拟源码

 一、deferred的功能及其使用

deferred的底层是基于callbacks实现的,建议再熟悉callbacks的内部机制前提下阅读这篇博客,如果需要了解callbacks可以参考:jQuery使用():Callbacks回调函数列表之异步编程(含源码分析)

  • deferred.done() 向成功状态的回调函数列表中添加回调方法
  • deferred.fail() 向失败状态的回调函数列表中添加回调方法
  • deferred.progress() 向正在进行状态的回调函数列表中添加回调方法
  • deferred.resolve() 触发成功状态的回调函数列表所有方法
  • deferred.reject() 触发失败状态的回调函数列表所有方法
  • deferred.notify() 触发正在进行状态的回调函数列表(当resolve或reject被触发后就不能触发notify)

本质上done、fail、progress实质上分别指向了缓存三种状态的回调对象的add方法,统一由deferred方法引用管理,resolve、reject、notify同理分别指向了三个状态的回调对象的fire方法(内部实现指向fireWith,为了设置this指向deferred或者promise)。下面使用这六个方法来实现一个模拟异步状态回调事件:

 1 var df = $.Deferred();
 2 //注册成功的回调函数
 3 df.done(function(a){
 4     console.log('ho yeah I do it!' + a);
 5 });
 6 //注册失败的回调函数
 7 df.fail(function(a){
 8     console.log('sorry I am loser...' + a);
 9 });
10 //注册进行时的函数
11 df.progress(function(a){
12     console.log("waiting???" + a);
13 });
14 //用定时器模拟一个异步状态回调事件 >60 表示成功 ; < 50表示失败 ; 60><50表示正在进行
15 setInterval(function(){
16     var score = Math.random() * 100;
17     if(score > 60){
18         df.resolve("simpleness");
19     }else if(score < 50){
20         df.reject("difficult");
21     }else{
22         df.notify('be surprised to be dumb');
23     }
24 },1000);

通过deferred对象同时管理三个回调对象,让代码语义化实现的更优雅,同时也降低了代码的冗余。添加回调函数的形式于callback。add方法一致,可以实现多个同时添加。但是deferred做的远远不止这些,由于deferred对象是同时存在添加和执行两种方法,为了保证调用只能在特定位置触发,deferred还实现了promise对象只用来实现注册方法,promis对象上只有指向回调对象add的done、fail、progress方法,以及一个then用来更便捷的添加回调函数的方法。

所以上面的方法可以修改为:

 1 //用定时器模拟一个异步状态回调事件 >60 表示成功 ; < 50表示失败 ; 60><50表示正在进行
 2 function createScore(){
 3     var df = $.Deferred();
 4     setInterval(function(){
 5         var score = Math.random() * 100;
 6         if(score > 60){
 7             df.resolve("simpleness");
 8         }else if(score < 50){
 9             df.reject("difficult");
10         }else{
11             df.notify('be surprised to be dumb');
12         }
13     },1000);
14     return df.promise();
15 }
16 var pom = createScore();
17 //注册成功的回调函数
18 pom.done(function(a){
19     console.log('ho yeah I do it!' + a);
20 });
21 //注册失败的回调函数
22 pom.fail(function(a){
23     console.log('sorry I am loser...' + a);
24 });
25 //注册进行时的函数
26 pom.progress(function(a){
27     console.log("waiting???" + a);
28 });

上面的代码修改后,就是一个盗版的ajax的事件反馈机制,在jQuery.ajax中源码就是通过deferred的异步队列来实现的。前面还有提到then更便捷的回调注册方法又是什么呢?下面来看通过then方法改造上面的代码:

//上面的代码18~28行可以采用这段代码替换
pom.then(function(a){console.log('ho yeah I do it!' + a);
},function(a){console.log('sorry I am loser...' + a);
},function(a){console.log("waiting???" + a);
});

这个模拟示例可以完全采用这两种代码任意一种实现,那这两种代码存在什么区别呢?区别就是then方法可以传入三个参数,分别对应的是done、fail、progress方法的函数注册,但是then不能给同一个状态注册多个回调函数,而done、fail、progress可以像callback.add()那样同时注册多个函数,因为done、fail、progress本身就是指向add()别称。但是then方法还有另一个功能就是能连续注册来替代这种缺陷,并且还可以接收来自上一个方法的返回值作为参数:

 1 pom.then(function(a){
 2     console.log('ho yeah I do it!' + a);
 3     return "oK"
 4 },function(a){
 5     console.log('sorry I am loser...' + a);
 6     return "no"
 7 },function(a){
 8     console.log("waiting???" + a);
 9     return "why"
10 }).then(function(param){
11     console.log(param);//oK
12 },function(param){
13     console.log(param);//no
14 },function(param){
15     console.log(param);//why
16 });

但是需要注意的是,返回值不能是新的deferred对象,如果是一个新的异步延迟对象返回,后面继续使用then方法就是作用在新的异步延迟对象上。

 二、deferred的实现原理及模拟源码

这部分源码是基于jQuery使用():Callbacks回调函数列表之异步编程(含源码分析)的模拟回调函数列表对象实现的,没有测试jQuery的Callbacks对象,代码暂时实现了promise()方法,then()方法没有实现,今天有事,有时间再来添加。

 1 function clone(origin, target){
 2     for(var ele in origin){
 3         target[ele] = origin[ele];
 4     }
 5     return target;
 6 }        
 7 function Deferred(fuc){
 8     //异步延迟对象
 9     var deferred = {}
10     var tuples = [
11         ["resolve","done",Callback("once memory")],
12         ["reject","fail",Callback("once memory")],
13         ["notify","progress",Callback("memory")]
14     ];
15     var statesum = true;
16     //异步延迟对象的注册对象
17     var promise = {
18         //返回deferred的promise注册对象   
19         //源码中有obj的合并采用extend实现,这里写了一个简单的克隆方法
20         promise:function(obj){
21             return obj != null ? clone(promise,obj) : promise;
22         }
23     }
24     var pending = true;
25     for(var tuple in tuples){
26         var list = tuples[tuple][2];
27         //添加deferred的回调函数注册方法 done fail progress
28         promise[tuples[tuple][1]] = list.add;
29         //添加deferred的回调函数触发执行方法 resolve reject ontify
30         deferred[tuples[tuple][0]] = (function(i,obj){
31             return function(){
32                 if(pending){
33                     // console.log(this.state);
34                     deferred[tuples[i][0]+"With"](obj === deferred ? obj : promise,arguments);
35                     tuples[i][0] == "resolve" || tuples[i][0] == "reject" ? pending = false : "";
36                 }
37                 return obj;
38             }
39         })(tuple,this);
40         deferred[tuples[tuple][0] + "With"] = list.fireWith;
41     }
42     //将promise合并到deferred上 -- 同样采用克隆方法实现
43     promise.promise(deferred);
44     //fcn执行 上下文指向deferred  参数设置为deferred
45     if(fuc){
46         fuc.call(deferred,deferred);
47     }
48     return deferred;
49 }

 

转载于:https://www.cnblogs.com/ZheOneAndOnly/p/10549999.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/483749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客14392 猴子吃香蕉

链接&#xff1a;https://ac.nowcoder.com/acm/problem/14392 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 65536K&#xff0c;其他语言131072K 64bit IO Format: %lld 题目描述 有n只猴子&#xff0c;第i只猴子每…

AI科普微视频丨人类的智能是如何产生的?

来源&#xff1a;中国人工智能学会人工智能是如何产生的&#xff1f;人工智能的法杖为什么充满曲折&#xff1f;为什么说图灵是人工智能之父&#xff1f;为加大AI科普力度&#xff0c;推动文化传播&#xff0c;中国人工智能学会推出了“AI科普微视频”栏目&#xff0c;以每期2~…

结队编程项目——四则运算

一、项目与分析 项目功能 自动生成小学四则运算题目&#xff08;加、减、乘、除&#xff09;并统计正确率 支持整数支持多运算符&#xff08;比如生成包含100个运算符的题目&#xff09;支持真分数分析 生成整数与真分数&#xff1a;实现了生成真分数即可利用分数的约分机制使其…

# 进度条的制作

import time for i in range(100):sys.stdout.write("#") # 在屏幕上输出#time.sleep(0.1)sys.stdout.flush() # 刷新功能 转载于:https://www.cnblogs.com/quanag/p/10657915.html

牛客14355 翻硬币

链接&#xff1a;https://ac.nowcoder.com/acm/problem/14355 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld 题目描述 小明正在玩一个“翻硬币”的游戏。 …

2021诺奖预测出炉!16名学者获得最新一届“引文桂冠奖”

图片来源&#xff1a;Pixabay来源&#xff1a;公众号“科睿唯安”2002 年以来&#xff0c;科睿唯安每年都会基于 Web of Science 平台上的论文和引文数据&#xff0c;遴选诺贝尔奖奖项所涉及的生理学或医学、物理学、化学及经济学领域中全球最具影响力的顶尖研究人员&#xff0…

[转帖]2015年时微软Win3.1崩溃迫使巴黎奥利机场短暂关闭

https://www.ithome.com/html/it/188796.htm IT之家讯 2015年11月14日消息&#xff0c;上周法国巴黎奥利机场因为微软的Windows 3.1系统出现故障不得不迫使所有飞机降落并暂时关闭机场。对&#xff0c;你没看错&#xff0c;就是Windows 3.1&#xff0c;这款操作系统于1992年发布…

牛客14386 水仙花数

链接&#xff1a;https://ac.nowcoder.com/acm/problem/14386 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld 题目描述 水仙花数是指一个N位正整数&#xf…

华为发布《智能世界2030》报告,多维探索未来十年趋势

来源&#xff1a;华为2021年9月22日&#xff0c;华为携手产业伙伴举办了智能世界2030论坛。华为常务董事、ICT产品与解决方案总裁汪涛以“无界探索&#xff0c;翻开未来”为主题演讲&#xff0c;发布了《智能世界2030》报告。这是华为首次通过定量与定性结合的方式&#xff0c;…

类定义(课下选做)

1、设计思路 1.根据题目要求覆盖&#xff08;Override&#xff09;toString方法、覆盖equals方法&#xff0c;即重写这两个方法&#xff1b; 2.根据题目要求定义至少三个构造方法&#xff0c;接收并初始化这些数据&#xff1b; 3.创建一个测试类Bookshelf, 其中的main方法创建并…

我们不用「元宇宙」这个词!苹果CEO库克:我们称其为AR

来源&#xff1a;Time&新智元近日&#xff0c;在登上时代周刊的百大人物之后&#xff0c;苹果CEO库克再次接受了杂志的采访。虽然内容千篇一律&#xff0c;但是最有趣的莫过于拒绝「元宇宙」这个说法了。「这就是所谓的元宇宙吗&#xff1f;」Time的记者问道。「不&#xf…

牛客13584 日历中的数字

链接&#xff1a;https://ac.nowcoder.com/acm/problem/13584 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 131072K&#xff0c;其他语言262144K 64bit IO Format: %lld 题目描述 ElemenT马上就要毕业了&#xff0…

详解HTML的a标签(超链接标签)

1、什么是<a>标签 <a> 标签定义超链接&#xff0c;用于从一张页面链接到另一张页面。  <a> 元素最重要的属性是 href 属性&#xff0c;它指示链接的目标。 2、<a>标签的几个重要属性 2.1、href 规定链接指向的页面的 URL。 1. 链接https、http地址&a…

许竹青、骆艾荣:数字城市的理念演化、主要类别及未来趋势研究

来源&#xff1a;本文原刊于《中国科技论坛》2021年8月第8期摘要&#xff1a;城市与技术的关系由来已久&#xff0c;但将“数字”这一技术概念与城市连接成为专有名词却是新事物。本文从技术变迁的外生驱动和城市发展问题的内生需求两个角度探讨数字城市兴起及发展的动因&#…

牛客20701 神秘钥匙

链接&#xff1a;https://ac.nowcoder.com/acm/problem/20701 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld 题目描述 clccle一行&#x1d45b;个人来到了…

《深入浅出vue.js》阅读笔记之数组变化侦测

1、如何追踪变化 数组的侦测方式和对象不同&#xff0c;比如&#xff1a; this.list.push(1) 此时并不会像改变对象一样触发setter。 同理&#xff0c;要侦测数组的变化意味着我们在改变数组的时候得到通知&#xff0c;如图&#xff0c;我们可以用一个拦截器覆盖Array.prototyp…

时隔16年,Science再次发布“全世界最前沿的125个科学问题”!

来源&#xff1a;文汇报《科学》杂志曾于创刊125周年之际发布过125个推动基础科学研究的科学难题&#xff0c;对指引其后十几年的科学发展产生积极影响。16年过去了&#xff0c;科技发展日新月异&#xff0c;科学突破层出不穷&#xff0c;许多问题得到一定程度的解答&#xff0…

牛客19115 选择颜色

链接&#xff1a;https://ac.nowcoder.com/acm/problem/19115 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld 题目描述 n个人排成一个环形&#xff0c;每个…

虹软人脸识别Android Sample Code

AFR_FSDKInterface engine new AFR_FSDKEngine();//用来存放提取到的人脸信息, face_1 是注册的人脸&#xff0c;face_2 是要识别的人脸 AFR_FSDKFace face1 new AFR_FSDKFace(); AFR_FSDKFace face2 new AFR_FSDKFace();//初始化人脸识别引擎&#xff0c;使用时请替换申请的…

当人工智能遇上计算社会科学……

来源&#xff1a;微信公号&#xff1a;计算社会科学家原文出处:《人民论坛学术前沿》作者&#xff1a;华东师范大学哲学系教授 郦全民近年来&#xff0c;由深度学习引爆的“人工智能”&#xff0c;迅速成为科技领域乃至日常生活中的流行词&#xff1b;差不多同时&#xff0c;在…