我什么时候会使用JQuery.Callbacks?

时间:2011-11-09 20:06:27

标签: jquery jquery-callback jquery-1.7

我正在查看添加到jQuery 1.7的新内容,我看到他们现在有了jQuery.Callbacks()http://api.jquery.com/jQuery.Callbacks/

该文档向您展示了如何使用jQuery.callbacks(),但没有任何适用的示例,以便我何时使用它们。

似乎你可以在回调列表中添加/删除回调,你可以执行jQuery.callbacks()。fire(args),但这只会触发该列表中的所有回调。也许我错过了一些东西,但这似乎没什么用处。

在我第一次看到这个新功能时,我认为你可以将它与键/值对一起使用。然后,这将提供一种在应用程序的单个位置管理回调函数的简单方法。像

这样的东西
$.callbacks.add("foo", myFunction);

然后例如,如果我想在我的函数结束时调用该回调,我可以做类似的事情

$.callbacks().fire("foo", args);

然而,看起来你不能触发特定的回调,你只能使用给定的参数或者没有激活所有回调。

我看到的最接近的事情是能够给.fire()函数一个上下文来设置“this”属性

.fireWith(context, args)

但这也没有多大帮助。

  1. 我误解了文档吗?

  2. 如果这是所需的功能,那么有用的示例是什么。

6 个答案:

答案 0 :(得分:16)

稍微扩展@Rockets answer并澄清一些混淆:

人们可能需要使用jQuery $.Callbacks的原因是多方面的:

  1. 用户在一个功能中有很多代码,并希望将其拆分
  2. 他们获取该信息并通过jQuery回调函数发送,然后允许他们将代码拆分为更易于管理的部分。 所以(例如)如果你看@Rocket's code

    var clickCallbacks = $.Callbacks();
    
    clickCallbacks.add(function() { //one one function piece
        //parse and do something on the scope of `this`
        var c = parseInt(this.text(), 10);
        this.text(c + 1);
    });
    clickCallbacks.add(function(id) { //add a second non-related function piece
        //do something with the arguments that were passed
        $('span', '#last').text(id);
    });
    
    $('.click').click(function() {
        var $ele = $(this).next('div').find('[id^="clickCount"]');
        clickCallbacks.fireWith($ele, [this.id]); //do two separate but related things.
    });
    
  3. 您现在拥有的是多个回调批次的功能,您可以在需要时调用它们,而无需在整个代码中进行如此多的更改。

答案 1 :(得分:12)

当您使用相同的方法更新不同的DOM元素时,我可以看到回调很有用。

这是一个俗气的例子:http://jsfiddle.net/UX5Ln/

var clickCallbacks = $.Callbacks();

clickCallbacks.add(function() {
    var c = parseInt(this.text(), 10);
    this.text(c + 1);
});
clickCallbacks.add(function(id) {
    $('span', '#last').text(id);
});

$('.click').click(function() {
    var $ele = $(this).next('div').find('[id^="clickCount"]');
    clickCallbacks.fireWith($ele, [this.id]);
});

当您点击某些内容时,它会更新点击计数器和“最后点击”。

答案 2 :(得分:8)

(几乎)开箱即用的jQuery Pub / Sub系统

这是恕我直言最有趣的应用程序,并且由于答案中没有明确明确(虽然有些人暗示了这些用法),但我将它添加到这个相对较旧的帖子中。

  

NB: jQuery docs中有一个示例清楚地显示了该用法,但我想这是在问题发布后添加的。

Pub/sub,又名观察者模式,是一种在应用程序中提升松散耦合单一责任的模式。对象不是让对象直接调用其他对象的方法,而是订阅特定的任务或活动,并在发生时通知。有关使用发布/订阅模式的好处的更详细说明,您可以查看Why would one use the Publish/Subscribe pattern (in JS/jQuery)?

当然,this was possible with custom events使用trigger.on().off(),但我发现jQuery.Callbacks 很多更合适完成任务,生成更清晰的代码。

以下是jQuery documentation的示例摘要:

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!
*/

答案 3 :(得分:3)

似乎$.Callbacks作为实现细节开始:一种管理函数列表并使用相同参数调用给定列表中的所有函数的方法。有点像C#的multicast delegates,还有其他功能,比如你可以传递的标志来自定义列表的行为。

一个很好的例子可能是jQuery在内部使用$.Callbacks来实现其ready事件。 bindReady()初始化回调列表:

readyList = jQuery.Callbacks( "once memory" );

注意oncememory标志,确保只调用一次回调列表,并且在调用列表后添加的函数将立即被调用。

然后,ready()将指定的处理程序添加到该列表中:

ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();

    // Add the callback
    readyList.add( fn );

    return this;
}

最后,当DOM准备就绪时会触发回调列表:

readyList.fireWith( document, [ jQuery ] );

所有ready处理程序在同一文档的上下文中调用,并具有对全局jQuery对象的相同引用。它们只能被调用一次,并且从那时起将立即调用传递给ready()的其他处理程序,所有这些都是$.Callbacks的礼貌。

答案 4 :(得分:2)

我没有看到任何具体的设置上下文,但由于你可以传递任意数量的参数,这可能是有用的。您还可以使自己的约定将标志作为第一个参数传递,并且如果它们不打算处理剩余的参数列表,则会立即返回false。

我遇到过类似这样的事情可能有用的情况,但是使用了bind()和trigger()而不是自定义事件。想象一下您正在为新消息轮询服务的一些消息处理系统(基于Web的聊天室或电子邮件客户端)。一个功能可能是在一个范围内设置一个数字或在某些事情发生时显示一个咆哮。另一个可能是更新网格。使用触发器,您必须为每个侦听器触发事件​​并从eventData“展开”传递的参数,使用回调它只是一个火,而您的侦听器是带有简单参数列表的简单javascript函数。

回调并不完全是革命性的,但它会使代码更少,更清晰。

答案 5 :(得分:0)

我正在开发一款具有大量业务逻辑和至少11项外部服务的应用。如果您可以使用Callbacks之类的东西编写自己的流控制类和行为,而不是试图在Deferred实现上强制您的意愿,这确实有助于保持正确。