Foreword
jQuery.Callbacks was added to jquery after version 1.7. It was extracted from the _Deferred object in version 1.6. It is mainly used to perform add, remove, fire, lock and other operations of function queues, and provides once , memory, unique, stopOnFalse four options for some special control.
Function introduction
jq’s Callbacks module mainly provides services for other modules. It is like a gentle little woman, paying silently behind the scenes. Deferred is like a giant, so prominent in jq, but internally, he is served by Callbacks.
Several states of Callbacks:
The callback function only executes once OnFalse -- Terminate the callback list and continue execution when return false is encountered
Several simple methods of Callbacks that I implemented myself
var cb = Callback('memory once') // 得到一个拥有记忆功能并只执行一次的回调模块
Since we need to get different instances based on a certain state, we can determine that we need an object to store the state
var callbackState = {}
We passed 'memory once' to the Callback function , how do we record these two states? Here, we implement it with a function written in jq, as follows:
var createCallbackState = function (options) { var states = options.split(' ') var obj = {} for (var i = 0; i < states.length; i++) { obj[states[i]] = true } return obj }
The above code changes 'memory once' into {memory: true, once: true}, if there is this object in the state cache object, it will be returned directly. If not, it will be created first and then returned.
Next, is the entire code of the Callback function. Let’s start with the code
var Callback = function (options) { var state = callbackState[options] //获取状态模式 if (!state) { callbackState[options] = state = createCallbackState(options) } var list = [], // 回调函数列表 memory, // 存储是否为 记忆状态 has = function (fn) { for (var i = 0; i < list.length; i++) { if (list[i] === fn) { return true } } return false }, add = function () { var i = 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) { var i = 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) { return has(fn) }, clear: function () { list = [] } } }
After the Callback function is executed, it returns an object, and then the object contains several simple functions.
Let me introduce the implementation of this part.
First of all, like jq, I also defined the internal add, fire, and has methods. The main reason is the logical need. Once and memory state control are implemented in the method that returns the object. The internal add and fire methods are pure additions. and trigger functions.
Let’s look at the cb.add method first. The add method can receive multiple functions, so
add.apply(null,arguments)
Use the internal add to add the function
The next part of the function is to determine whether the callback module is memory Status, students who understand the Deferred module should know that this module is a Promise mode, subscribing to the callback function of the success or failure status, and then triggering it at a certain moment. This mode refers to the Callback in the memory state. This mode has a strange Where, if you publish successfully first, but the callback list is empty, then the program will not fail to publish, but wait for the successful callback function to be added. Once the callback function is added, it will be executed immediately.
is the following code
// 如果memory模式并且已经拥有了memory信息,立刻触发函数 if (state.memory && memory) { fire(memory[0], memory[1]) list = [] }
Tip: 'If you publish successfully first, but the callback list is empty, then the program will not fail to publish, but will wait for the successful callback function to be added. Once the callback function is added, it will immediately Execute his understanding of the following code
var cb = Callback('memory') // 得到记忆功能的回调模块 cb.fire() // 触发回调队列 cb.add(fn) //添加回调函数,自动执行了! function fn () { console.log('fn') }
If it is in a non-memory state, the above code is invalid. It needs to be fired again to execute.
After the above, the fire function is easy to understand. fire can receive two parameters, function context and function parameter array.
Connected with the memory state code in add, the following code is the operation in the memory state during fire
// 如果memory模式,并且list是空,代表触发在添加前,保存memory信息 if (state.memory && !list.length) { memory = [context, args] return }
If it is the memory state and the callback list is empty, save the function execution context and parameter array, etc. Execute immediately when add.
In addition to the above, the code is very simple and easy to understand. The Callback function ends here. It is a very simple function. The only thing that is difficult to understand is the memory status.