1. 定义
弹跳这个词对于每个 js 用户来说都是那么熟悉,但从字面上理解却很容易。 Callback就是交换,Callbacks就是多次回调。 在JQuery中,是弹跳队列jquery执行,即很多弹跳函数都存放在Callbacks Queue中,即按顺序执行(这个函数是按照加入队列的顺序触发的jquery执行,并不意味着第二次弹跳是第一次运行完成后调用,因为js中存在异步)队列中的每个反弹函数。 我们也可以这样理解,这就是我们常说的风暴订阅和发布模式。 说到暴风雨,我们很容易理解。 每次触发器调用反弹函数时。
那么回调有什么用呢? 在JQuery中,Deffered使用Callbacks来实现Promise/A+标准。 它解决了异步同步问题和代码的深度嵌套。
2.Callbacks中的main方法
callbacks.add() 回调列表中添加一个回调或回调的集合。 callbacks.disable() 禁用回调列表中的回调 callbacks.disabled() 确定回调列表是否已被禁用。 callbacks.empty() 从列表中删除所有的回调. callbacks.fire() 用给定的参数调用所有的回调 callbacks.fired() 访问给定的上下文和参数列表中的所有回调。 callbacks.fireWith() 访问给定的上下文和参数列表中的所有回调。 callbacks.has() 确定列表中是否提供一个回调 callbacks.lock() 锁定当前状态的回调列表。 callbacks.locked() 确定回调列表是否已被锁定。 callbacks.remove() 从回调列表中的删除一个回调或回调集合。
三、主要参数
options = { once: 回调对象仅触发(fire)一次 memory: 若true,在Callbacks正则触发事件过程中,新加入回调函数,新加入的函数将在旧的回调函数队列执行完成之后,促发新加入的. unique: 在add操作中,相同的函数仅只一次被添加(push)到回调列表中 stopOnFalse:当回调函数返回false,中断列表中的回调循环调用,且memory === false,阻止在add操作中将要触发的回调 }
4. 源代码
jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === "string" ? ( optionsCache[ options ] || createOptions( options ) ) : jQuery.extend( {}, options ); var // Flag to know if list is currently firing firing,//是否正在触发 // Last fire value (for non-forgettable lists) memory,// // Flag to know if list was already fired fired,//是否已经触发过 // End of the loop when firing firingLength,//回调队列的长度 // Index of currently firing callback (modified by remove if needed) firingIndex,//标记当前触发队列的标号(也就是记录当前触发到第几个) // First callback to fire (used internally by add and fireWith) firingStart,//回调队列的起始标号 // Actual callback list list = [],//回调队列, 保存回调函数 // Stack of fire calls for repeatable lists //触发队列, 多次触发的队列才把触发的上下文入栈 //(同一个时间只有一次触发队列执行,也就是说连续触发fire两次队列,第一次执行完,才会执行第二次[第一次触发,第二次触发...]) stack = !options.once && [], // Fire callbacks //触发回调函数, self使用函数fire实现最终的回调函数的调用 fire = function( data ) { //如果是memory类型管理器, 记住fire的事件data,以便下次add的时候可以重新fire这个事件 memory = options.memory && data; fired = true;//标记为回调队列已经触发过 firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; firing = true;//标记为正在触发回调队列 //注意,这里只能按照顺序触发队列中的回调函数,不能保证按照触发的顺序完成所有的回调函数,如果存在异步 for ( ; list && firingIndex -1 ) { list.splice( index, 1 ); // Handle firing indexes if ( firing ) { if ( index <= firingLength ) { firingLength--; } if ( index -1 : !!( list && list.length ); }, // Remove all callbacks from the list empty: function() { list = []; firingLength = 0; return this; }, // Have the list do nothing anymore disable: function() { list = stack = memory = undefined; return this; }, // Is it disabled? disabled: function() { return !list; }, // Lock the list in its current state lock: function() { stack = undefined; if ( !memory ) { self.disable(); } return this; }, // Is it locked? locked: function() { return !stack; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( list && ( !fired || stack ) ) { args = args || []; //栈中存的上下文格式是[上下文(默认self为上下文), [参数1, 参数2...]] args = [ context, args.slice ? args.slice() : args ]; //触发回调队列的时候,如果上一次触发还正在进行,那么久把当前触发的上下文和参数保存到栈stack中, //这样, 上一次触发回调完成之后,可以从栈中取出上下文和参数,接着触发下一次 if ( firing ) { stack.push( args ); } else {//如果当前不是正在触发状态,立即执行当前的触发 fire( args ); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; //返回self return self; };