博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JQuery日记6.9 Promise/A之Callbacks
阅读量:4630 次
发布时间:2019-06-09

本文共 8895 字,大约阅读时间需要 29 分钟。

JQuery并没有简单的使用一个Array来存储回调函数,而是通过JQuery.Callbacks(options)返回一个self对象,此对象能够动态的add,remove和fire回调函数队列.此函数须要说明的是options參数,它是一个string,这个string由四个參数随意组合而成
options:
once:回调函数仅仅运行一次
memory:调用add时触发回调函数使用fire时传入的參数.
unique:回调函数仅仅能被加入到队列一次
stopOnFlase:有一个回调函数返回false,停止运行以下的回调函数.
JQuery.Callbacks(options)内的变量依据不同传參有不同的意思,这些变量由闭包引用扩大其生命周期,以在外部改变其值,下面进行说明
memory:假设options不包括'memory'字符串,memeory为false,其它为上一次fire(args)的參数.
fired:回调函数列表是否被触发过.
firing:回调函数列表是否正在被触发.为何要这个參数呢?由于假设在回调函数内调用了add,remove,fire 方法时会改变回调函数列表的状态(開始触发的位置,触发长度等等,这些是控制要运行回调函数列表中哪些函数的标志),此时其回调函数函数列表正在处于触发中,必须能够及时反映(修正触发位置,触发长度等等)回调函数列表的变化,以便在回调函数运行的循环中下一次迭代能够正确的触发回调函数列表.
firingStart:回调函数列表运行的開始位置.
firingLength:再运行几个回调函数
firingIndex:正在触发的函数在回调函数列表中的位置
list:存放回调函数
stack:假设在回调函数中调用fire或fireWith方法,将fire或fireWith传入的上下文和參数先入栈,稍后再用栈中的參数来作为參数运行回调函数中调用的fire或fireWidth

注:不解的是走到stack.push分支时是在回调函数里调用fire或fireWidth,但这样会导致死循环,这个stack究竟怎么回事?还请明确的同学告知我一下。!

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 // Last fire value (for non-forgettable lists)            memory,             // Flag to know if list was already fired            fired,             // Flag to know if list is currently firing            firing,             // First callback to fire (used internally by add and fireWith)            firingStart,             // End of the loop when firing            firingLength,             // Index of currently firing callback (modified by remove if needed)            firingIndex,             // Actual callback list            list = [],             // Stack of fire calls for repeatable lists             // 假设没有配置once,stack为数组             // stack存放反复时fire參数            stack = !options.once && [],             // Fire callbacks            fire = function( data ) {                   //memory 为false或fire时传入的參数                  memory = options.memory && data;                  fired = true;                   //当前触发位置                  firingIndex = firingStart || 0;                   //触发回调函数队列的起始位置                  firingStart = 0;                   //待触发的回调函数队列长度                  firingLength = list.length;                   //正在触发标识设置为true                   //仅仅有在Callbacks的回调函数里此值才会为true                  firing = true;                   for ( ; list && firingIndex < firingLength; firingIndex++ ) {                         //若配置了stopOnFalse当回调函数队列中函数返回值为false                         if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {                               //memory设置为false                              memory = false; // To prevent further calls using add                               //不再运行后面的回调函数                               break;                        }                  }                   //回调函数运行结束                  firing = false;                   if ( list ) {                         //未配置once                         if ( stack ) {                               //运行在回调函数里调用的fire                               if ( stack.length ) {                                    fire( stack.shift() );                              }                         //清空回调函数列表,但此callbacks仍可用                        } else if ( memory ) {                              list = [];                         //让闭包的那些引用能够销毁                        } else {                              self.disable();                        }                  }            },             // Actual Callbacks object            self = {                   // Add a callback or a collection of callbacks to the list                  add: function() {                         if ( list ) {                               // First, we save the current length                               // 将加入回调函数之前将当前callbacks的长度设为运行開始                               var start = list.length;                              ( function add( args ) {                                    jQuery.each( args, function( _, arg ) {                                           var type = jQuery.type( arg );                                           if ( type === "function" ) {                                                 // 假设未设置unique或者回调函数列表里没有此函数                                                 // 在回调函数队列里加上此函数                                                 if ( !options.unique || !self.has( arg ) ) {                                                      list.push( arg );                                                }                                           // 假设arg是个类数组,再递归add                                          } else if ( arg && arg.length && type !== "string" ) {                                                 // Inspect recursively                                                add( arg );                                          }                                    });                              })( arguments );                               // Do we need to add the callbacks to the                               // current firing batch?                               //在正在触发的回调函数中调用add方法会走此分支                               if ( firing ) {                                     //立马反应要触发回调函数长度的改变                                    firingLength = list.length;                               // With memory, if we're not firing then                               // we should call right away                              } else if ( memory ) {                                     //改变触发的開始位置为未加入前的回调队列长度                                    firingStart = start;                                    fire( memory );                              }                        }                         return this;                  },                   // Remove a callback from the list                  remove: function() {                         if ( list ) {                              jQuery.each( arguments, function( _, arg ) {                                     //arg所在list的索引                                     var index;                                     while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {                                           //删除                                          list.splice( index, 1 );                                           // Handle firing indexes                                           //假设在回调函数里调用remove                                           if ( firing ) {                                                 //要删除的回调函数是还没触发的                                                 if ( index <= firingLength ) {                                                       //触发的长度减一                                                       firingLength--;                                                }                                                 //要删除的是已经触发过的函数                                                 if ( index <= firingIndex ) {                                                       //正要触发索引减一                                                       firingIndex--;                                                }                                          }                                    }                              });                        }                         return this;                  },                   // Check if a given callback is in the list.                   // If no argument is given, return whether or not list has callbacks attached.                  has: function( fn ) {                         return fn ?

jQuery.inArray( fn, list ) > -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 //锁住当前的状态,不会运行在回调函数里调用fire或fireWidth 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 || []; args = [ context, args.slice ? args.slice() : args ]; //?事实上这里有一点不解,走到这个分 //是在在回调函数里调通fire或fireWidth,但这样会导致死循环 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; } }; return self; };

转载于:https://www.cnblogs.com/zfyouxi/p/5211917.html

你可能感兴趣的文章
洛谷 [P3480] KAM-Pebbles
查看>>
操作系统任务调度问题
查看>>
day02-python 基础02
查看>>
.net下Ueditor配置(主要讲解上传功能配置)
查看>>
std::string的Copy-on-Write:不如想象中美好
查看>>
KONG -- 配置 service 并添加 key-auth
查看>>
多重继承和有内嵌对象时构造函数调用顺序
查看>>
C#编码规范
查看>>
信号、槽位及布局
查看>>
webpack + vue
查看>>
启动JvisualVM提示"无法检测到本地java应用程序"的解决方案
查看>>
抓包实现脚本编写--手持机
查看>>
PHP+nginx 线上服务研究(一)
查看>>
Python学习教程:超干货—Python3内置模块之json编解码方法小结
查看>>
谷歌浏览器的一个新特点—关于获取iframe的parent对象
查看>>
iOS开发Swift篇—(二)变量和常量
查看>>
Windows底层开发前期学习准备工作
查看>>
【C语言及程序设计】项目1-39-3:反序数
查看>>
算法——查找常用字符
查看>>
ANDORID~支持的设备
查看>>