## 返回值:jQueryjQuery.callbacks(flags)

### 概述

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

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

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

### 参数

#### flags V1.7

一个用空格标记分隔的标志可选列表,用来改变回调列表中的行为

### 示例

#### 入门描述:

以下是两个样品的方法命名fn1 and fn2:

##### jQuery 代码:

    function fn1( value ){
        console.log( value );
    }

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

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

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

    callbacks.add( fn2 );
    callbacks.fire( "bar!" ); // outputs: bar!, fn2 says: bar!

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

用于以上的两个具体的方法： .add() 和 .fire() .add() 支持添加新的回调回调列表, 而.fire() 提供了一种用于处理在同一列表中的回调方法的途径.

另一种方法由$.Callbacks 的remove()，用于从回调列表中删除一个特定的回调。下面是.remove() 使用的一个例子:

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

    callbacks.add( fn2 );
    callbacks.fire( "bar!" ); // outputs: bar!, fn2 says: bar!

    callbacks.remove(fn2);
    callbacks.fire( "foobar" );

    // only outputs foobar, as fn2 has been removed.

#### 支持的 Flags描述:

这个 flags 参数是$.Callbacks()的一个可选参数, 结构为一个用空格标记分隔的标志可选列表,用来改变回调列表中的行为 (比如. $.Callbacks( 'unique stopOnFalse' )).

可用的 flags:

- once: 确保这个回调列表只执行一次(像一个递延 Deferred).
- 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
    *//code>

$.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，有一个累积效应，类似“&&”。这意味着它可能结合创建回调名单，unique 和确保如果名单已经触发，将有更多的回调调用最新的触发值 (i.e.$.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（ Observer模式）背后的一般思路 是促进应用程序的松散耦合。而比对其他对象的方法调用的单个对象，一个对象，而不是另一个对象的一个特定的任务或活动，并通知当它发生。观察家也被称为订阅者，我们指的出版商（或主体）观察对象。出版商事件发生时通知用户

作为一个组件$.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( "its been published!" );