jquery.Callbacks的实现详解
前言
jQuery.Callbacks是jquery在1.7版本之后加入的,是从1.6版中的_Deferred对象中抽离的,主要用来进行函数队列的add、remove、fire、lock等操作,并提供once、memory、unique、stopOnFalse四个option进行一些特殊的控制。
功能介绍
jq的Callbacks模块主要是为其他模块提供服务的,他就像一个温柔的小女人,在背后默默地付出。Deferred就像一个巨人,在jq中那么的突出,但在内部,他受到Callbacks的服务。
Callbacks的几种状态:
once --回调函数只执行一次
unique --函数不能重复添加到回调列表中
memory --状态记忆,主要用于Deferred中
stopOnFalse --遇到returnfalse终止回调列表继续执行
我自己实现的Callbacks的几个简单的方法
add --向对应的回调函数列表添加一个函数
fire --触发回调,回调函数列表依次执行函数
has --回调函数列表是否存在传入函数
clear --清空回调函数列表
整体结构
首先,我们要向得到一个想要的Callbacks模块,需要这样做:
varcb=Callback('memoryonce')//得到一个拥有记忆功能并只执行一次的回调模块
由于我们需要基于一定状态来得到不同的实例,我们可以确定,我们需要一个存储状态的对象
varcallbackState={}
我们给Callback函数传入了'memoryonce',我们怎么记录这两个状态呢,在这里,仿jq来写的一个函数来实现,如下:
varcreateCallbackState=function(options){ varstates=options.split('') varobj={} for(vari=0;i<states.length;i++){ obj[states[i]]=true } returnobj }
以上代码,将'memoryonce' 变成了{memory:true,once:true},如果状态缓存对象里有这个对象,直接返回,没有的话先创建再返回。
接下来,就是Callback函数的全部代码了,先上代码
varCallback=function(options){ varstate=callbackState[options]//获取状态模式 if(!state){ callbackState[options]=state=createCallbackState(options) } varlist=[],//回调函数列表 memory,//存储是否为记忆状态 has=function(fn){ for(vari=0;i<list.length;i++){ if(list[i]===fn){ returntrue } } returnfalse }, add=function(){ vari=0, args=arguments, len=args.length for(;i<len;i++){ if(state.unique&&has(args[i])){//如果是unique状态下并回调列表已经拥有该函数,则不添加 continue } list.push(args[i]) } }, fire=function(context,args){ vari=0, len=list.length, item for(;i<len;i++){ item=list[i] if(item.apply(context,args)===false&&state.stopOnFalse){//如果函数运行返回false,并且是stopOnFalse状态,终止循环 break; } } } return{ add:function(){ add.apply(null,arguments) //如果memory模式并且已经拥有了memory信息,接着出发函数 if(state.memory&&memory){ fire(memory[0],memory[1]) list=[] } }, fire:function(context,args){ //如果memory模式,并且list是空,代表触发在添加前,保存memory信息 if(state.memory&&!list.length){ memory=[context,args] return } fire(context,args) if(state.once){ this.clear() } }, has:function(fn){ returnhas(fn) }, clear:function(){ list=[] } } }
Callback函数执行后,返回一个对象,然后该对象包含了几个简单的功能。
下面我来介绍一下这部分的实现。
首先,如jq一样,我也定义了内部的add,fire,has方法,主要原因是逻辑需要,在返回对象的方法中实现once,memory状态控制,内部的add,fire方法是纯粹的添加和触发函数。
先来看cb.add方法,add方法可以接收多个函数,因此
add.apply(null,arguments)
使用内部的add做添加功能
再往下的一部分的功能是判断这个回调模块是否是memory状态,理解Deferred模块的同学应该知道,该模块是Promise模式,订阅成功或失败状态的回调函数,然后再某一时刻触发他,这个模式便引用了memory状态下的Callback,这个模式有一个奇怪的地方,如果你先发布成功,但是回调列表空空如也,那么程序并不会发布失败,而是等待成功回调函数的加入,一但回调函数加入,立刻执行他。
就是如下代码
//如果memory模式并且已经拥有了memory信息,立刻触发函数 if(state.memory&&memory){ fire(memory[0],memory[1]) list=[] }
提示:‘如果你先发布成功,但是回调列表空空如也,那么程序并不会发布失败,而是等待成功回调函数的加入,一但回调函数加入,立刻执行他'的理解如下代码
varcb=Callback('memory')//得到记忆功能的回调模块 cb.fire()//触发回调队列 cb.add(fn)//添加回调函数,自动执行了! functionfn(){ console.log('fn') }
如果在非memory状态,以上代码无效。需要再次fire才会执行。
经过上述,fire函数也好理解了,fire可接收两个参数,函数上下文,函数参数数组。
与add中memory状态的代码连串起来,以下代码就是fire时memory状态下的操作
//如果memory模式,并且list是空,代表触发在添加前,保存memory信息 if(state.memory&&!list.length){ memory=[context,args] return }
如果是memory状态,回调列表为空,就保存函数执行上下文和参数数组,等add时立刻执行。
除了上述以外,代码就很简单易懂啦,Callback函数就到这里了,很简单的功能,唯一一点不好理解的就是memory状态。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。