41

我正在查看添加到 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. 如果这是所需的功能,那么有哪些有用的适用示例。

4

6 回答 6

16

扩展@Rockets 回答一下并消除一些困惑:

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

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

    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. 您现在可以拥有的是多个回调函数批次,您现在可以在认为有必要时调用它们,而无需在整个代码中进行如此多的更改。
于 2011-11-09T21:40:30.773 回答
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]);
});

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

于 2011-11-09T21:22:23.620 回答
8

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

恕我直言,这是最有趣的应用程序,并且由于答案中没有明确说明(尽管有些确实暗示了用法),因此我将其添加到这篇相对较旧的帖子中。

注意:在jQuery docs中通过示例清楚地说明了用法,但我想它是在发布问题后添加的。

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

当然,使用,和自定义事件是可能的,但我发现它适合该任务,生成更清晰的代码。trigger.on().off()jQuery.Callbacks

这是jQuery 文档中的示例片段:

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!
*/
于 2013-08-29T15:56:35.240 回答
3

似乎$.Callbacks从一个实现细节开始:一种管理函数列表并使用相同参数调用给定列表中所有函数的方法。有点像 C# 的多播委托,具有附加功能,例如您可以传递的标志以自定义列表的行为。

一个很好的例子可能是 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.

于 2011-11-09T21:36:59.550 回答
2

我没有看到任何关于设置上下文的具体提及,但由于您可以传递任意数量的参数,这可能会很有用。您还可以制定自己的约定,将标志作为第一个参数传递,并让侦听器在不打算处理剩余参数列表时立即返回 false。

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

回调并不完全是革命性的,但它会减少和清洁代码。

于 2011-11-09T20:47:39.937 回答
0

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

于 2011-11-09T21:12:53.767 回答