Easy Tutorial
❮ Misc Jquery Deferred Misc Contains ❯

jQuery.Callbacks() Method

jQuery Miscellaneous Methods

Example

Adding a callback function to the $.Callbacks list

$(function () { 
    function fn1( value ) {
        alert( value );
    }
    function fn2( value ) {
        fn1("fn2 says: " + value);
        return false;
    }
    var callbacks = $.Callbacks();
    callbacks.add( fn1 ); 
    // Output: foo!
    callbacks.fire( "foo!" );
    callbacks.add( fn2 );
    // Output: bar!, fn2 says: bar!
    callbacks.fire( "bar!" );
})

Definition and Usage

$.Callbacks() refers to a multi-purpose callback function list object, providing a powerful way to manage callback function queues.

Tip: $.Callbacks is used internally by jQuery, such as for .ajax, $.Deferred, etc., to provide foundational functionality. It can also be used in similar components, such as custom plugins.


Syntax

Parameter Description
flags Optional. String type. A space-separated optional list of flags to change the behavior of the callback list.

More Examples

Below is an example of using .remove() to remove a specific callback from the callback list

Example

$(function () { 
    function fn1( value ) {
        alert( value );
    }
    function fn2( value ) {
        fn1("fn2 says: " + value);
        return false;
    }
    var callbacks = $.Callbacks();
    callbacks.add( fn1 );
    // Output: foo!
    callbacks.fire( "foo!" );
    callbacks.add( fn2 ); 
    // Output: bar!, fn2 says: bar!
    callbacks.fire( "bar!" );
    callbacks.remove( fn2 );
    // Only outputs foobar, fn2 has been removed.
    callbacks.fire( "foobar" );
})

Supported Flags Parameter

The flags parameter is an optional parameter for $.Callbacks(), structured as a space-separated list of flags to change the behavior of the callback list (e.g., $.Callbacks('unique stopOnFalse')). The available flags are:

Parameter Description
once Ensures the callback list only executes once.
memory Caches the last fired parameters, and when add() is called, immediately invokes the newly added callback with the cached parameters.

Below is an example of $.Callbacks('once')

Example

$(function () { 
    function fn1( value ) {
        alert( value );
    }
    function fn2( value ) {
        fn1("fn2 says: " + value);
        return false;
    }
    var callbacks = $.Callbacks('once');
    callbacks.add( fn1 );
    callbacks.fire( "foo" ); 
    callbacks.add( fn2 );
    callbacks.fire( "bar" );
    callbacks.remove( fn2 );
    callbacks.fire( "foobar" );
    /* Only outputs: foo */
})

Below is an example of $.Callbacks('memory')

Example

$(function () { 
    function fn1( value ) {
        alert( value );
    }
    function fn2( value ) {
        fn1("fn2 says: " + value);
        return false;
    }
    var callbacks = $.Callbacks('memory');
    callbacks.add( fn1 );
    callbacks.fire( "foo" );
    callbacks.add( fn2 );
    callbacks.fire( "bar" );
    callbacks.remove( fn2 );
    callbacks.fire( "foobar" );
    /* Outputs:
    foo
    fn2 says: foo
    bar
    fn2 says: bar
    foobar
    */
})

Below is an example of $.Callbacks('unique')

Example

$(function () { 
    function fn1( value ) {
        alert( value );
    }
    function fn2( value ) {
        fn1("fn2 says: " + value);
        return false;
    }
    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" );
    /* Outputs:
    foo
    bar
    fn2 says: bar
    foobar
    */
})

Below is an example of $.Callbacks('stopOnFalse')

Example

$(function () { 
    function fn1( value ) {
        alert( 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" );
    /* Outputs:
    foo
    bar
    foobar
    */
})

$.Callbacks() supports setting multiple flags (identifiers) at once, which has an accumulative effect, similar to "&&".

Example

$(function () { 
    function fn1( value ) {
        alert( 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" ); 
    /* Outputs:
    foo
    fn2 says: foo
    bar
    fn2 says: bar
    baz
    fn2 says: baz
    foobar
    */
})

The $.Callbacks method can also be separated, for example:

Example

$(function () { 
    function fn1( value ) {
        alert( value );
    }
    var callbacks = $.Callbacks(),
    add = callbacks.add,
    remove = callbacks.remove,
    fire = callbacks.fire;
    add( fn1 );
    fire( "hello world" );
    remove( fn1 ); 
    /* Outputs: hello world */
})

$.Callbacks, $.Deferred, and Pub/Sub

The general idea behind pub/sub (observer pattern) is to promote loose coupling and efficient communication in applications. Observers, also known as subscribers, point to the subject being observed. The publisher notifies subscribers when an event occurs.

As a demonstration of the components created by $.Callbacks(), you can implement a Pub/Sub system using just the callback function list. By treating $.Callbacks as a message queue, you can implement message publishing and subscribing as follows:

Example

$(function () { 
    function fn1( value ) {
      alert( value );
      return false;
    }

    function fn2( value ) {
      fn1("fn2 says: " + value);
      return false;
    }
    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;
    };
    var topic = jQuery.Topic( "example" );
    topic.subscribe( fn1 );
    topic.publish( "foo" );
    topic.subscribe( fn2 );
    topic.publish( "bar" );
    topic.unsubscribe( fn2 );
    topic.publish( "foobar" );
    /* Outputs:
    foo
    fn2 says: foo
    bar
    fn2 says: bar
    foobar
    */
})
{
    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!");
/* Output:
hello world!
fn2 says: hello world!
woo! mail!*/
})

Further improvements using $.Deferreds can ensure that publishers can only publish notifications to subscribers when specific tasks are completed (or resolved). See the example code below:

## Example

$(function () { function fn1(value) { alert(value); return false; }

function fn2(value) {
    fn1("fn2 says: " + value);
    return false;
}
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;
};
// Subscribe to mailArrived notifications
$.Topic("mailArrived").subscribe(fn1);
// Create a new Deferred object
var dfd = $.Deferred();
// Define a new topic (not publishing directly)
var topic = $.Topic("mailArrived");
// When the Deferred is resolved, publish a notification to subscribers
dfd.done(topic.publish);
/* This will delay the message being passed to the subscribers,
it integrates complex programs (such as waiting for an
Ajax call to complete) so that the message is actually only
published once. */
// Resolve.
dfd.resolve("Published!");

})


---

[jQuery Miscellaneous Methods](jquery-ref-misc.html)
❮ Misc Jquery Deferred Misc Contains ❯