jQuery._Deferred 理解

本系列文章都是基于jquery1.6.4的,请参照源代码。

今天,我们来研究jQuery._Deferred方法。和往常一样,先放源代码。

jQuery.extend({
	// Create a simple deferred (one callbacks list)
	_Deferred: function() {
		var // callbacks list
			callbacks = [],
			// stored [ context , args ]
			fired,
			// to avoid firing when already doing so
			firing,
			// flag to know if the deferred has been cancelled
			cancelled,
			// the deferred itself
			deferred  = {

				// done( f1, f2, ...)
				done: function() {
					if ( !cancelled ) {
						var args = arguments,
							i,
							length,
							elem,
							type,
							_fired;
						if ( fired ) {
							_fired = fired;
							fired = 0;
						}
						for ( i = 0, length = args.length; i < length; i++ ) {
							elem = args[ i ];
							type = jQuery.type( elem );
							if ( type === "array" ) {
								deferred.done.apply( deferred, elem );
							} else if ( type === "function" ) {
								callbacks.push( elem );
							}
						}
						if ( _fired ) {
							deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
						}
					}
					return this;
				},

				// resolve with given context and args
				resolveWith: function( context, args ) {
					if ( !cancelled && !fired && !firing ) {
						// make sure args are available (#8421)
						args = args || [];
						firing = 1;
						try {
							while( callbacks[ 0 ] ) {
								callbacks.shift().apply( context, args );
							}
						}
						finally {
							fired = [ context, args ];
							firing = 0;
						}
					}
					return this;
				},

				// resolve with this as context and given arguments
				resolve: function() {
					deferred.resolveWith( this, arguments );
					return this;
				},

				// Has this deferred been resolved?
				isResolved: function() {
					return !!( firing || fired );
				},

				// Cancel
				cancel: function() {
					cancelled = 1;
					callbacks = [];
					return this;
				}
			};

		return deferred;
	},
         //下面是Deferred方法和when方法
        Deferred: function( func ) {},
        when: function( firstParam ) {}
)};
jQuery._Deferred方法是通过jQuery.extend方法加入到jQuery中的,关于jQuery.extend方法,请查看我的另外一篇博文(现在还没有写)。

从第5-13我们可以看出_Deferred函数对象拥有5个属性,分别是callbacks(数组),fired,firing,cancelled,deferred(对象)。

callbacks数组是存放_Deferred对象通过done方法注册的函数,这时候我们可以根据第34行和52行这两条语句,我们可以知道callbacks模拟了队列,因此通过done注册的回调函数,触发时回调函数是根据传入的顺序来执行的。

fired属性表示_Deferred对象是否已经是满足状态,根据第56行,我们可知道此时fired的值得形式是[context,args] (后面解释),而未满足状态的fired是undefined或者0。

firing=1(第50行)表示_Deferred对象正在从未满足状态转换到满足状态,防止_Deferred对象多次被resolve(第46行),当_Deferred对象为满足状态时,firing=0(第57行)。

cancelled属性表示_Deferred对象是否被取消,也就是是否可以注册回调函数,对于被取消的_Derferred对象是不可以触发和注册回调函数的。deferred对象是在_Deferred函数内定义的,最终被返回,实际_Defered对象就是指的deferred对象,这样是为了保护前面的四个变量;

deferred对象有done,resolve,resolveWith,isResolved,cancel这些函数。现在我们来分别看这5个函数,从最简单的开始:

cancel函数只有三句(76-78),把cancelled设为1,清空callback数组,被调用了cancelled的_Deferred对象是不可被触发的。

isResolved函数是判断_Deferred对象处于什么样的状态,当_Deferred对象处于满足状态(fired=[context,args])或者是正在从未满足状态到满足状态的转换过程中都是true,其他为false,这儿(第71行)有两个是为了在firing和fired都是undefined的时候返回true。

resolve函数可以传入参数,并把this(通常就是deferred对象)和传递进来的参数arguments传递给resolveWith函数。当触发是,实际真正处理的resolveWith函数(第65行)。下面我们来看看resolveWith函数。

resolveWith的函数的第一句(第46行):说明只有没有取消的并且_Deferred对象是未满足的才可以触发回调函数。第49行把firing设为1表示_Deferred对象正在从未满足状态转换为满足状态,而第51句的while循环和52行的callbacks.shift().apply(context,args),通过done注册的回调函数安装注册的顺序被触发。

下面是本篇文章的最重要的部分,done函数的分析。done函数的参数可以是函数,或者是元素是函数的数组;我们一句一句来分析done函数,第18-23行定义了六个变量,其中_fired变量是为了保存fired变量的值,防止fired变量被修改引起的副作用;我们知道_Defered对象是满足状态的时候,通过done注册的函数是会被立即执行的。这可以从第37-39知道,因为_Deferred对象是刚刚是满足的(第26行有fired=0),那么if(_fired)就会为真,然后会调用resolveWith方法;如果此时_Defered是正在转换的,那么第28-36行的回调函数已经被注册到了callbacks,那么现在通过done注册的回调函数也会被立即执行的(因为有另外一个resolveWith调用还没有完成);那我们现在来仔细看看注册回调函数的部分。

for循环对done的每一个参数进行处理,在for循环内,type表示了参数的类型,如果是数组(第31行),那么通过在进行一步的deferred.done.apply( deferred, elem )调用把数组内的函数(可以嵌套数组(语法来讲,当然我们也不会这么折腾自己),还有数组具有length属性,因此对于数组参数在进行done(这个时候只有一个数组参数)调用,可以再次通过for循环,把内部的函数注册到callbacks);如果type是函数那么直接调用callbacks.push,把回调函数放到callbacks的尾端。保证了回调函数的调用顺序。


今天的_Deferred理解就到这里了,第一次写博客,语言组织不太习惯,还请大家指点。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值