zoukankan      html  css  js  c++  java
  • 读jQuery之十九(多用途回调函数列表对象)

    $.Callbacks 是在版本 1.7 中新加入的。它是一个多用途的回调函数列表对象,提供了一种强大的方法来管理回调函数队列。

    整个 $.Callbacks 的源码不到 200 行,它是一个工厂函数,使用函数调用方式(非new,它不是一个类)创建对象,它有一个可选参数flags用来设置回调函数的行为。

    $.Callbacks 是在 jQuery 内部使用,如为 $.ajax,$.Deferred 等组件提供基础功能的函数。它也可以用在类似功能的一些组件中,如自己开发的插件。

    $.Callbacks构造的对象(以callbacks示例)主要包括以下方法:

    1. callbacks.add
    2. callbacks.remove
    3. callbacks.has
    4. callbacks.empty
    5. callbacks.disable
    6. callbacks.fire
    7. callbacks.fireWith
    8. callbacks.fired
    9. callbacks.lock
    10. callbacks.locked

    1. callbacks.add 添加一个函数到回调队列

    function fn1() {
    	console.log(1)
    }
    function fn2() {
    	console.log(2)
    }
    
    var callbacks = $.Callbacks();
    // 方式1
    callbacks.add(fn1);
    // 方式2 一次添加多个回调函数
    callbacks.add(fn1, fn2);
    // 方式3 传数组
    callbacks.add([fn1, fn2]);
    // 方式4 函数和数组掺和
    callbacks.add(fn1, [fn2]);
    

    传数组进去实际在add内部判断如果是数组会递归调用私有的add函数。此外,需注意add方法默认不去重,比如这里fn1添加两次,fire时会触发两次。私有add方法有趣,它使用了具名函数立即执行其名仅在函数内可用。如图中所圈之处

    2. callbacks.remove 从回调队列中删除一个函数

    function fn1() {
        console.log(1)
    }
    function fn2() {
        console.log(2)
    }
    var callbacks = $.Callbacks();
    callbacks.add(fn1, fn2);
    callbacks.remove(fn1);
    

    此时fire只会触发fn2了。

    此外remove方法会把添加多次的函数如fn1,全部删除掉。为此还和cmcnick讨论为啥remove内部不用if而用while(开始我以为是jQuery写错了)。如下

    var callbacks = $.Callbacks();
    callbacks.add(fn1, fn2, fn1, fn2);
    callbacks.remove(fn1);
    

    此时会把add两次的fn1都删掉,fire时只触发fn2两次。换成if则只删fn1一次。

    3. callbacks.has 判断是否添加过某回调函数,不想重复添加时很有用

    function fn1() {
        console.log(1)
    }
    var callbacks = $.Callbacks();
    callbacks.add(fn1);
    if (!callbacks.has(fn1)) {
        callbacks.add(fn1);
    }
    

    4. callbacks.empty 清空所有的回调函数

    function fn1() {
    	console.log(1)
    }
    function fn2() {
    	console.log(2)
    }
    var callbacks = $.Callbacks();
    callbacks.add(fn1);
    callbacks.add(fn2);
    callbacks.empty();
    

    此时再fire不会触发任何函数。empty函数实现很简单,只是把内部的队列管理对象list重置为一个空数组。这里可以了解清空数组的几种方式

    5. callbacks.disable 禁用该对象

    function fn1() {
        console.log(1)
    }
    function fn2() {
        console.log(2)
    }
    var callbacks = $.Callbacks();
    callbacks.disable();
    callbacks.add(fn1); // 不起作用
    callbacks.add(fn2); // 不起作用
    callback.remove(fn1); // 不起作用
    callbacks.fire(); // 不起作用
    

    调用后再使用add, remove, fire等方法均不起作用。该方法内不是实际是将队列管理对象list、stack、memory都置undefined了。

    6. callbacks.fire 主动触发添加回调函数

    function fn() {
        console.log(this); // 上下文是callbacks
        console.log(arguments); // [3]
    }
    var callbacks = $.Callbacks();
    callbacks.add(fn);
    callback.fire(3);
    

    前面已经提到了,fire方法用来触发回调函数,默认的上下文是callbacks对象,还可以传参给回调函数。

    7. callbacks.fireWith 同fire,但可以指定执行上下文

    function fn() {
        console.log(this); // 上下文是person
        console.log(arguments); // [3]
    }
    var person = {name: 'jack'};
    var callbacks = $.Callbacks();
    callbacks.add(fn);
    callback.fireWith(person, 3);
    

    其实fire内部调用的是fireWith,只是将上下文指定为this了,而this正是$.Callbacks构造的对象。

    8. callbacks.fired 判断是否有主动触发过(调用fire或fireWith方法)

    function fn1() {
        console.log(1)
    }
    var callbacks = $.Callbacks();
    callbacks.add(fn1);
    callbacks.fired(); // false
    callbacks.fire();
    callbacks.fired(); // true
    

    注意,只要调用过一次fire或fireWith就会返回true。

    9. callbacks.lock 锁定队列的状态

    10. callbacks.locked 判断是否锁定状态

    $.Callbacks构造时可配置的参数Flags是可选的,字符串类型以空格分隔,有如下

    1. once
    2. memory
    3. unique
    4. stopOnFalse

    1. once 确保回调函数仅执行一次

    function fn() {
        console.log(1)
    }
    var callbacks = $.Callbacks('once');
    callbacks.add(fn);
    callbacks.fire(); // 打印1
    callbacks.fire(); // fn不再触发
    

    2. memory 记忆callbacks

    function fn1() {
    	console.log(1)
    }
    function fn2() {
    	console.log(2)
    }
    var callbacks = $.Callbacks('memory');
    callbacks.add(fn1);
    callbacks.fire(); // 必须先fire
    callbacks.add(fn2); // 此时会立即触发fn2
    

    memory有点绕,本意是记忆的意思。实际它的用法有点诡异,需结合特定场景来看(如jQuery.Deferred)。当首次调用fire后,之后每次add都会立即触发。比如先callbacks.fire(),再callbacks.add(fn1),这时fn1会立即被调用。

    如果是批量添加的,也都会被触发

    function fn1() {
    	console.log(1)
    }
    function fn2() {
    	console.log(2)
    }
    function fn3() {
    	console.log(3)
    }
    var callbacks = $.Callbacks('memory');
    callbacks.add(fn1);
    callbacks.fire();
    callbacks.add([fn2, fn3]); // output 2, 3
    

    3. unique 去除重复的回调函数

    function fn1() {
    	console.log(1)
    }
    function fn2() {
    	console.log(2)
    }
    var callbacks = $.Callbacks('unique');
    callbacks.add(fn1);
    callbacks.add([fn1, fn2]); // 再次添加fn1
    callbacks.fire(); // output 1, 2
    

    这个很好理解,之前用has判断去重,使用unique属性则更方便。本例先add一次fn1,第二次再add时内部则会去重。因此最后fire时只输出“1,2”而不是“1,1,2”。

    4. stopOnFalse 回调函数返回false时中断回调队列的迭代

    function fn1() {
    	console.log(1)
    }
    function fn2() {
    	console.log(2)
    	return false // 注意这里
    }
    function fn3() {
    	console.log(3)
    }
    var callbacks = $.Callbacks('stopOnFalse');
    callbacks.add(fn1, fn2, fn3);
    callbacks.fire(); // output 1,2
    

    从该属性名就能知了它的意图,即回调函数通过return false来停止后续的回调执行。该示例添加了3个回调,fn2中使用return false,当fire执行到fn2时会停止执行,后续的fn3就不会被调用了。

    用$.Callbacks实现观察者模式

    // 观察者模式
    var observer = {
    	hash: {},
    	subscribe: function(id, callback) {
    		if (typeof id !== 'string') {
    			return
    		}
    		if (!this.hash[id]) {
    			this.hash[id] = $.Callbacks()
    			this.hash[id].add(callback)
    		} else {
    			this.hash[id].add(callback)
    		}
    	},
    	publish: function(id) {
    		if (!this.hash[id]) {
    			return
    		}
    		this.hash[id].fire(id)
    	}
    }
    
    // 订阅
    observer.subscribe('mailArrived', function() {
    	alert('来信了')
    })
    observer.subscribe('mailArrived', function() {
    	alert('又来信了')
    })
    observer.subscribe('mailSend', function() {
    	alert('发信成功')
    })
    
    // 发布
    setTimeout(function() {
    	observer.publish('mailArrived')
    }, 5000)
    setTimeout(function() {
    	observer.publish('mailSend')
    }, 10000)
    

      

    注:阅读版本为1.8.3

  • 相关阅读:
    Echarts Jqplot嵌extjs4 windows 装配方法
    法学类人猿生存方案--升华成掌握可能的方式
    LeetCode Merge k Sorted Lists 解决报告
    Swift
    Swift
    Swift
    Swift
    Swift
    Swift
    Swift
  • 原文地址:https://www.cnblogs.com/snandy/p/2770237.html
Copyright © 2011-2022 走看看