• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • jQuery.Callbacks()

    一个多用途的回调列表对象,提供了强大的的方式来管理回调函数列表。

    jQuery.Callbacks(flags)
    • flags类型: String。一个用空格标记分隔的标志可选列表,用来改变回调列表中的行为。

    $.Callbacks()的内部提供了jQuery的$.ajax()$.Deferred()基本功能组件。它可以用来作为类似基础定义的新组件的功能。

    $.Callbacks()支持的方法,包括callbacks.add(),callbacks.remove(),callbacks.fire()callbacks.disable().

    入门

    以下是两个方法命名fn1fn2:

    function fn1( value ) {
        console.log( value );
    }
     
    function fn2( value ) {
        fn1("fn2 says: " + value);
        return false;
    }
    

    这些可以添加为回调函数作为一个$.Callbacks的列表,并调用如下:

    var callbacks = $.Callbacks();
    callbacks.add( fn1 );
     
    // outputs: foo!
    callbacks.fire( "foo!" );
     
    callbacks.add( fn2 );
     
    // outputs: bar!, fn2 says: bar!
    callbacks.fire( "bar!" );
    

    这样做的结果是,它使构造复杂的回调列表变得简单,输入值可以通过尽可能多的函数根据需要轻松使用。

    用于以上的两个具体的方法:.add()方法支持将新的回调添加到回调列表,而.fire()方法执行添加的功能,并提供一种传递参数的方法,该参数将由同一列表中的回调处理。

    另一种方法由$.Callbacks.remove(),它具有从回调列表中删除特定回调的功能。

    下面是.remove()使用的一个例子:

    var callbacks = $.Callbacks();
    callbacks.add( fn1 );
     
    // outputs: foo!
    callbacks.fire( "foo!" );
     
    callbacks.add( fn2 );
     
    // outputs: bar!, fn2 says: bar!
    callbacks.fire( "bar!" );
     
    callbacks.remove( fn2 );
     
    // only outputs foobar, as fn2 has been removed.
    callbacks.fire( "foobar" );
    

    支持Flags

    这个flags参数是$.Callbacks()的一个可选参数,结构为由空格分隔的字符串列表,这些字符串更改了回调列表的行为(比如.$.Callbacks('unique stopOnFalse')).

    可用的 flags:

    • once:确保回调列表只能被触发一次(如延迟)
    • memory:跟踪先前的值,并在使用最新的“已存储”值(如Deferred)立即触发列表后调用添加的任何回调。
    • unique:确保回调只能添加一次(因此列表中没有重复项)。
    • stopOnFalse:当回调返回false时中断呼叫。

    默认情况下,回调列表的作用类似于事件回调列表,并且可以“触发”多次。

    有关flags理想使用方法的示例,请参见下文

    $.Callbacks("once")

    var callbacks = $.Callbacks( "once" );
    callbacks.add( fn1 );
    callbacks.fire( "foo" );
    callbacks.add( fn2 );
    callbacks.fire( "bar" );
    callbacks.remove( fn2 );
    callbacks.fire( "foobar" );
     
    /*
    output:
    foo
    */
    

    $.Callbacks("memory")

    var callbacks = $.Callbacks( "memory" );
    callbacks.add( fn1 );
    callbacks.fire( "foo" );
    callbacks.add( fn2 );
    callbacks.fire( "bar" );
    callbacks.remove( fn2 );
    callbacks.fire( "foobar" );
     
    /*
    output:
    foo
    fn2 says:foo
    bar
    fn2 says:bar
    foobar
    */
    

    $.Callbacks("unique")

    var callbacks = $.Callbacks( "unique" );
    callbacks.add( fn1 );
    callbacks.fire( "foo" );
    callbacks.add( fn1 ); // repeat addition
    callbacks.add( fn2 );
    callbacks.fire( "bar" );
    callbacks.remove( fn2 );
    callbacks.fire( "foobar" );
     
    /*
    output:
    foo
    bar
    fn2 says:bar
    foobar
    */
    

    $.Callbacks("stopOnFalse")

    function fn1( value ){
        console.log( value );
        return false;
    }
     
    function fn2( value ){
        fn1( "fn2 says: " + value );
        return false;
    }
     
    var callbacks = $.Callbacks( "stopOnFalse" );
    callbacks.add( fn1 );
    callbacks.fire( "foo" );
    callbacks.add( fn2 );
    callbacks.fire( "bar" );
    callbacks.remove( fn2 );
    callbacks.fire( "foobar" );
     
    /*
    output:
    foo
    bar
    foobar
    */
    

    因为$.Callbacks()支持一个列表的flags(标识)而不仅仅是一个,设置几个flags(标识),有一个累积效应,类似“&&”。这意味着可以组合标志来创建回调列表,这两个列表都是唯一的,并确保列表是否已被触发,添加更多回调将使用最新的触发值(即$.Callbacks("unique memory"))调用它。

    $.Callbacks('unique memory')

    function fn1( value ) {
        console.log( value );
        return false;
    }
     
    function fn2( value ) {
        fn1( "fn2 says: " + value );
        return false;
    }
     
    var callbacks = $.Callbacks( "unique memory" );
    callbacks.add( fn1 );
    callbacks.fire( "foo" );
    callbacks.add( fn1 ); // repeat addition
    callbacks.add( fn2 );
    callbacks.fire( "bar" );
    callbacks.add( fn2 );
    callbacks.fire( "baz" );
    callbacks.remove( fn2 );
    callbacks.fire( "foobar" );
     
    /*
    output:
    foo
    fn2 says:foo
    bar
    fn2 says:bar
    baz
    fn2 says:baz
    foobar
    */
    

    Flag结合体是使用的$.Callbacks()内部的.done().fail()一个递延容器-它们都使用$.Callbacks('memory once').

    $.Callbacks方法也可以被分离,为方便起见应该有一个需要定义简写版本:

    var callbacks = $.Callbacks(),
        add = callbacks.add,
        remove = callbacks.remove,
        fire = callbacks.fire;
     
    add( fn1 );
    fire( "hello world" );
    remove( fn1 );
    

    $.Callbacks,$.Deferred and Pub/Sub

    pub/sub(发布/订阅,或观察者模式)背后的总体思想是促进应用程序之间的松耦合。一个对象而不是单个对象调用其他对象的方法,而是订阅另一个对象的特定任务或活动,并在该对象发生时得到通知。观察者也称为订阅者,我们将被观察的对象称为发布者(或主题)。事件发生时,发布者会通知订阅者。

    为了演示的组件创建功能$.Callbacks(),有可能仅使用回调列表来实现pub/sub系统。使用$.Callbacks()为主题的队列,用于发布和订阅主题可以实现如下的系统:

    var topics = {};
     
    jQuery.Topic = function( id ) {
        var callbacks,
            method,
            topic = id && topics[ id ];
     
        if ( !topic ) {
            callbacks = jQuery.Callbacks();
            topic = {
                publish: callbacks.fire,
                subscribe: callbacks.add,
                unsubscribe: callbacks.remove
            };
            if ( id ) {
                topics[ id ] = topic;
            }
        }
        return topic;
    };
    

    然后,应用程序的某些部分可以使用它轻松发布和订阅感兴趣的事件:

    // Subscribers
    $.Topic( "mailArrived" ).subscribe( fn1 );
    $.Topic( "mailArrived" ).subscribe( fn2 );
    $.Topic( "mailSent" ).subscribe( fn1 );
     
    // Publisher
    $.Topic( "mailArrived" ).publish( "hello world!" );
    $.Topic( "mailSent" ).publish( "woo! mail!" );
     
    // Here, "hello world!" gets pushed to fn1 and fn2
    // when the "mailArrived" notification is published
    // with "woo! mail!" also being pushed to fn1 when
    // the "mailSent" notification is published.
     
    /*
    output:
    hello world!
    fn2 says: hello world!
    woo! mail!
    */
    

    尽管这很有用,但可以进一步实施。使用$.Deferreds,可以确保发布者仅在完成(解决)特定任务后才发布订阅者的通知。请参阅下面的代码示例,以获取有关如何在实践中使用它

    // subscribe to the mailArrived notification
    $.Topic( "mailArrived" ).subscribe( fn1 );
     
    // create a new instance of Deferreds
    var dfd = $.Deferred();
     
    // define a new topic (without directly publishing)
    var topic = $.Topic( "mailArrived" );
     
    // when the deferred has been resolved, publish a
    // notification to subscribers
    dfd.done( topic.publish );
     
    // Here the Deferred is being resolved with a message
    // that will be passed back to subscribers. It's possible to
    // easily integrate this into a more complex routine
    // (eg. waiting on an ajax call to complete) so that
    // messages are only published once the task has actually
    // finished.
    dfd.resolve( "it's been published!" );
    

    下篇:callbacks.add()