位置: 编程技术 - 正文

谈谈jQuery之Deferred源码剖析(jquery deferred对象)

编辑:rootadmin

推荐整理分享谈谈jQuery之Deferred源码剖析(jquery deferred对象),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:简述jquery,jquery defered,jquery的deferred,jquery deffered,jquery的fadein,jquery defaultvalue,jquery defered,jquery deffered,内容如对您有帮助,希望把文章链接给更多的朋友!

一、前言

大约在夏季,我们谈过ES6的Promise,其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样,通过链式调用,避免层层嵌套,如下:

注:从jQuery1.8版本开始,then方法会返回一个新的受限制的deferred对象,即deferred.promise()—后续源码解读中我们会更加全面地了解到。因此,上述代码done中会打印'undefined'。

好了,通过上述示例代码,短暂的回顾了jQuery的Deferred使用后,我们一起来看看jQuery是怎么实现Deferred,当然解读jQuery的版本是大于1.8。

二、jQuery之Deferred源码剖析

整体架构,如下:

整体架构上,如果你了解设计模式中的工厂模式,那么不难看出,jQuery.Deferred就是一个工厂,每次执行jQuery.Deferred时,都会返回一个加工好的deferred对象。

接下来,我们再一步一步剖析上述代码。

首先,是数组tuples:

tuples一开始就为我们预先定义了三种状态—‘resolved'、'rejected'以及'pending',以及它们所对应的一系列值和操作,值得注意的是每种状态中,都调用了一个jQuery.Callbacks方法,如下:

它是个什么玩意儿?

细细品味了上述jQuery.Callbacks源码,如果你了解设计模式中的发布订阅者模式,不难发现,就是一个”自定义事件”嘛

所以,我们精简jQuery.Callbacks后,核心代码如下:

一目了然,我们每执行一次jQuery.Callbacks方法,它就会返回一个独立的自定义事件对象。在tuples每个状态中执行一次jQuery.Callbacks,也就豁然开朗了—为每个状态提供一个独立的空间来添加、删除以及触发事件。

好了,关于变量tuples,我们就算大致解读完了。

state就是deferred对象的状态值嘛,我们可以通过deferred.state方法获取(稍后会见到)。

promise就是一个拥有state、always、then、promise方法的对象,每个方法详解如下:

随后声明的一个空对象deferred。

promise.pipe=promise.then,就不累赘了,下面我们来看看jQuery.each(tuples, function(i, tuple){…})都干了什么,源码如下:

通过jQuery.each遍历tuples数组,并对其进行相关操作,比如我们拿tuples数组中的第一个元素举例:

['resolve', 'done', jQuery.Callbacks('once memory'), 'resolved']

第一步、声明的变量list指向jQuery.Callbacks返回的对象,stateString取值为'resolved'

第二步、为promise添加'done'属性,并指向第一步中list.add(fail和progress即指向属于各自的自定义事件对象)

第三步、判断stateString值,如果为'resolved'或'rejected'状态,那么就添加三个事件函数到对应的list列表中:

--改变state状态的函数 --禁止对应状态的处理,如'resolved'后,那么必定不会触发rejected状态咯,反之亦然 --禁止pending状态,都'resolved'或者'rejected'了,那么deferred肯定不会处于pending状态咯

第四步、为对象deferred,添加触发各自状态('resolved','rejected','pending')的fire相关方法:

--resolve、resolveWith --reject、rejectWith --notify、notifyWith

好了,jQuery.each(tuples, function(i, tuple){…})解读就到此结束了。

谈谈jQuery之Deferred源码剖析(jquery deferred对象)

总结:

通过jQuery.each遍历tuples,将tuples里的三种状态操作值done、fail以及progress添加到promise对象,并分别指向各自自定义对象中的add方法。如果状态为resolved或rejected,那么,再将三个特定函数添加到各自自定义对象的list列表下。随后,就是对deferred对象赋予三个状态各自的触发事件啦。

至此,promise、deferred对象如下图所示:

我们在前面讲解promise对象时,提到过它的promise属性,即为扩展promise对象,再回顾下:

所以接下来,源代码中的promise.promise(deferred),即为扩展deferred对象,让原来只有6个触发属性的deferred,同时拥有了promise对象的全部属性。

紧接着,func.call(deferred, deferred),即为执行参数func,当然,前提是func有值。值得注意的是,是将deferred作为func的执行对象以及执行参数的,这一点在promise.then中体现得淋淋尽致(稍后会细说)。

最后$.Deferred返回构建好的deferred对象。

到此,构建deferred整体流程走完。

三、细说promise.then

promise.then源码如下:

精简promise.then的源码如下:

整体架构上,可以清晰的看出,promise.then方法最后通过jQuery.Deferred返回了一个新的受限制的deferred对象,即deferred.promise,正因为这样,所以执行完then方法后,我们是不能通过deferred.pomise手动触发resolve、reject或notify的。

接下来,我们再一步一步剖析promise.then源码。

var fns = arguments不过就是将then方法中的参数赋予fns,在接下来的jQuery.each里使用。接着,就通过jQuery.Deferred返回了一个构建好的deferred对象,但是注意,在jQuery.Deferred里有个参数—匿名函数,还记得在上一小节末尾处,我们说过如果jQuery.Deferred里有值,就执行它,并将构建好的deferred作为执行对象和参数传入么:

固,promise.then方法中的newDefer指向通过jQuery.Deferred构建好的deferred。

紧接着,jQuery.each(tuples, function(i,tuple){…})处理,重点就是deferred[tuple[1]](function(){…});,注意,这里的deferred是then方法的父deferred哦,如下:

且tuple[1]为—done|fail|progress,在前面我们已经谈过,它们指向各自自定义事件对象的add方法。因此,也就明白了为什么deferred.resolve|reject|notify后,如果随后有then,会触发then方法的相关事件,如下:

但是,then方法后有then方法,又是怎么操作的呢?

它会判断then方法中的回调函数的返回值,如果是一个deferred对象,那么就将then方法自行创建的deferred对象中的相关触发事件,添加到回调函数中返回的deferred对象的对应的list列表中,这样,当我们触发回调函数中的相关触发事件后,也就会触发then方法的deferred对象了,从而,如果then方法后有then方法,也就关联了。

好了,那么如果then方法中的回调函数的返回值是一个非deferred对象呢?那么它就将这个返回值带上,直接触发then方法自行创建的deferred对象的相关事件,从而,如果then方法后有then方法,也就关联了。

好了,promise.then方法解决就算基本完毕。

四、思考

细细品来,大家有没有发现,其实promise.then就是通过作用域链,利用jQuery.Deferred中的变量deferred来关联父deferred的。如果,你还记得数据结构中的单链表,有没有发觉似曾相识呢,作者在这里通过jQuery.Deferred这个工厂构建每个deferred,然后利用作用域链相互关联,就如同单链表一样。

因此,借助这一思想,我们就一同模拟一个非常简单的Deferred,称作SimpleDef。主要作用就是每次我们执行SimpleDef函数,它都会返回一个构建好的simpleDef对象,该对象里面包含了三个方法done、then以及fire:

--done就如同add方法般,将done里的参数添加到它父simpleDef列表list中,并返回父simpleDef对象; --then就是将其参数func添加到父SimpleDef对象的列表list中,并返回一个新SimpleDef对象; --fire就是触发对应simpleDef对象的list列表里的所有函数。

实现代码如下:

测试代码如下:

标签: jquery deferred对象

本文链接地址:https://www.jiuchutong.com/biancheng/373939.html 转载请保留说明!

上一篇:Jquery Easyui选项卡组件Tab使用详解(10)(easyui选项卡)

下一篇:jQuery纵向导航菜单效果实现方法(纵向导航页面)

  • php常用图片处理类(php图片识别处理归类)

    php常用图片处理类(php图片识别处理归类)

  • PHP处理二进制数据的实现方法(php 二进制转十六进制)

    PHP处理二进制数据的实现方法(php 二进制转十六进制)

  • 浅析SQL Server的分页方式 ISNULL与COALESCE性能比较(sql server干嘛的)

    我们看到上述COALESCE合并的结果是可空的而ISNULL不是,有一点点不同。

    (3)COALESCE对列计算时需要持久化

    接下来我们看看二者最大的不同,我们通过计算列并且在其上面创建主键或者非空约束,看看ISNULL和COALESCE的区别

    我们再来看看COALESCE函数来计算列

    很明显我们需要对列进行持久化,通过添加PERSISTED关键字,如下即可。

    我们再来看看一个二者的不同

    我们到这里其实我们可以稍微概括下二者的区别:ISNULL着重于替换,而COALESCE着重于合并。COALESCE显示忽略了NULL并用空字符串填充并压缩,而ISNULL对NULL会用空字符串填充但不会压缩。

    (4)COALESCE函数支持超过两个参数

    对于多个参数输入,ISNULL函数需要嵌套调用,而COALESCE能够处理任何数量,至于上限不知,所以对于多个参数使用COALESCE更加,如下使用多个参数输入。

    SELECT COALESCE(a, b, c, d, e, f, g) FROM dbo.table;

    而对于ISNULL,我们需要这样做

    SELECT ISNULL(a, ISNULL(b, ISNULL(c, ISNULL(d, ISNULL(e, ISNULL(f, g)))))) FROM dbo.table;

    二者最终执行时和利用CASE一样

    (5)COALESCE和ISNULL二者性能比较

    我们来运行如下查询

    我们有查询四个场景:(1)两个参数都为NULL(2)第一个参数为NULL(3)第二个参数为NULL(4)两个参数都为NULL。每个场景测试十次,最终得出如下结果

    从上看出二者性能并未有什么太大差异,我们不需要太担心了吧,当然上述场景并未完全覆盖,至少还是能说明一部分。上述我们得到的结果查看的执行时间,现在我们再来看看二者查询执行计划。

    上述可能不太准确,还和硬件配置有关,也有可能COALESCE的性能差与ISNULL。二者性能应该是没什么很大差异。

    (6)ISNULL和自然语言描述不一致

    为何是和自然语言描述不一致呢?也就是说我们当判断某个值为NULL会做什么,不为NULL再做什么,这时用查询语言SQL描述如下:

    我们用自然语言角度来看,翻译为如果something为NULL我们做什么,这个时候是不一致的。因为在SQL Server中没有布尔值类型,上述我们只能进行如下转换

    (7)利用GUID看看奇葩的ISNULL

    在本节介绍之前我们再来看看一个例子,从而颠覆你的想法,让你发狂。

    SELECT ISNULL(NEWID(), 'JeffckyWang" class="img-responsive" alt="浅析SQL Server的分页方式 ISNULL与COALESCE性能比较(sql server干嘛的)">

    浅析SQL Server的分页方式 ISNULL与COALESCE性能比较(sql server干嘛的)

  • 怎么关闭Windows Defender具体步骤图解(怎么关闭windows登录密码)

    怎么关闭Windows Defender具体步骤图解(怎么关闭windows登录密码)

  • MAC电脑安装Ubuntu操作系统的技巧(mac电脑安装软件未受信任)

    MAC电脑安装Ubuntu操作系统的技巧(mac电脑安装软件未受信任)

  • 如何学习linux的建议 linux 学习心得 (怎么学linux)

    如何学习linux的建议 linux 学习心得 (怎么学linux)

  • Win7旗舰版系统还原按钮呈灰色不能使用问题的解决方法(Win7旗舰版系统镜像文件)

    Win7旗舰版系统还原按钮呈灰色不能使用问题的解决方法(Win7旗舰版系统镜像文件)

  • [安卓]手机管家(六)防盗之UI及自定义样式(安卓手机管家推荐)

    [安卓]手机管家(六)防盗之UI及自定义样式(安卓手机管家推荐)

  • 出口退税逾期申报说明怎样写
  • 价外费用纳税义务发生时间
  • 无形资产出资入股流程
  • 工会费个税税前扣除标准
  • 处置固定资产需要税务局备案吗
  • 应税销售行为的购买方为消费者个人的可以开专票吗
  • 个人独资企业个人所得税税率
  • 年底预收货款如何入账
  • 收到低值资产报废回收款账务处理
  • 增值税是否计入固定资产成本
  • 服务业预收款项怎么确认收入
  • 应收款确认坏账分录
  • 在筹建期间的费用属于什么
  • 幼儿园幼儿买花的通知
  • 个人户转账公户用途
  • 承租人转租需要退押金吗
  • 增值税普通发票有什么用
  • 证券公司期货业务管理办法
  • 帮你用好小微企业所得税优惠的7个案例
  • 孵化器 怎么赚钱
  • 小企业财务报表模板免费下载
  • 业务招待费不超过销售收入的5‰
  • 耕地建厂房补偿方法
  • 制作广告费用
  • 技术服务收入和产品服务收入举个例子
  • window10开始菜单
  • 公交车的乘车凭证能报销吗
  • 小规模开普票后怎么报增值税
  • 银行承兑汇票开出后可以撤销吗?
  • hkc中文是什么意思
  • 非居民所得税代扣代缴
  • window10怎么取消快捷方式
  • 会计分录内容包括
  • 小规模纳税人2023年出售使用过的
  • top命令可以看到哪些信息
  • zendframework3
  • 以其他方式取得土地使用权
  • 怎么缴销空白发票
  • 汇兑差额如何计算
  • ChatGLM-6B (介绍以及本地部署)
  • 使用vue要安装什么软件
  • discuz去除版权
  • 小微企业普惠性税收减免政策2022
  • 英文描述什么是利润表
  • 现金流量表本月数和本年累计数是相等的么
  • 未开票收入缴纳增值税做账
  • phpcms 生成首页
  • 本年利润有余额是什么意思
  • 出租设备收入交什么税
  • 银行会计核算方法的特点
  • 个人所得税分摊方式怎么填
  • 建筑服务预征缴纳税款期初余额怎么算
  • 流动资产周转天数高说明什么
  • 抚恤金的种类有多少种
  • 查补以前年度税款
  • 发票服务内容写错怎么办
  • 以前年度损益调整
  • 企业比赛奖金要交税吗
  • 企业职工福利费支出包括哪些内容
  • 其他应付款长期挂账违反什么规定
  • 财务费用怎么记账
  • mysqldump -h
  • mysql5.5怎么用
  • mysql 临时表
  • 系统警告设置
  • kb4012212安装失败
  • win8系统设置锁屏密码
  • win10再出变故 微软撤下Windows Update中11月份更新
  • opengl learn
  • unable to instantiate default
  • android 生成图片
  • dos删除指定后缀文件
  • shell中的括号
  • 置顶是什么意思呢
  • python 元类的作用
  • 国家税务局上海电子税务局app
  • 日本消费税是什么
  • 一般纳税人开劳务费税率是多少2023
  • 税局可以办理哪些业务
  • 河北电子税务局电话
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设