Когда я буду использовать JQuery.Callbacks? - PullRequest
41 голосов
/ 10 ноября 2011

Я просматривал новые вещи, добавленные в 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 ]

16 голосов
/ 10 ноября 2011

Чтобы подробнее остановиться на @ Rockets, ответьте и проясните некоторую путаницу:

Причина, по которой нужно использовать jQuery $.Callbacks, многогранна:

  1. Пользователь имеет много кода в одной функции и хочет разделить его на части
  2. Они берут эту информацию и отправляют ее через функцию обратного вызова jQuery, которая затем позволяет ему разбить свой код налучше управляемые части, с которыми можно работать.
    Так (например), если вы посмотрите на @ код Ракеты :

    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. Теперь вы можете иметь несколькопакеты функций обратного вызова, которые вы можете теперь вызывать всякий раз, когда сочтете это необходимым, без необходимости вносить так много изменений в ваш код.
12 голосов
/ 10 ноября 2011

Я вижу, что обратные вызовы полезны, когда вы обновляете разные элементы 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]);
});

Обновляет счетчик кликов и «последний клик», когда вы нажимаете на что-либо.

8 голосов
/ 29 августа 2013

An (почти) из коробки JQuery Pub / Sub system

Это ИМХО самое интересное приложение, и поскольку оно не было четко указано в ответах (хотя некоторые из них намекают на использование), я добавляю его в этот относительно старый пост.

NB: Использование четко указано, например, в jQuery docs , но, думаю, оно было добавлено после того, как вопрос был опубликован.

Pub / sub , он же шаблон наблюдателя , - это шаблон, который способствует слабой связи и единственной ответственности в приложении. Вместо того, чтобы иметь объекты, вызывающие непосредственно методы других объектов, объекты вместо этого подписываются на определенную задачу или действие и получают уведомление, когда это происходит. Для более подробного объяснения преимуществ использования шаблона Pub / Sub вы можете проверить Зачем использовать шаблон Publish / Subscribe (в 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!
*/
3 голосов
/ 10 ноября 2011

Кажется, что $.Callbacks начался как деталь реализации: средство для управления списками функций и вызова всех функций в данном списке с одинаковыми аргументами. Немного похоже на многоадресные делегаты C # с дополнительными функциями, такими как флаги, которые вы можете передать для настройки поведения списка.

Хорошим примером может быть то, что jQuery использует $.Callbacks для реализации своего события ready. bindReady() инициализирует список обратного вызова:

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

Обратите внимание на флаги once и memory, которые гарантируют, что список обратных вызовов будет вызываться только один раз, а функции, добавленные после вызова списка, будут вызываться немедленно.

Затем 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.

2 голосов
/ 10 ноября 2011

Я не вижу конкретного упоминания о настройке контекста, но, поскольку вы можете передать произвольное количество аргументов, это потенциально может быть полезно. Вы также можете заключить собственное соглашение о передаче флага в качестве первого аргумента и немедленном возвращении слушателями значения false, если они не предназначены для обработки списка оставшихся аргументов.

Я сталкивался со случаями, когда что-то подобное могло быть полезным, но вместо этого использовал bind () и trigger () с пользовательскими событиями. Представьте себе систему обработки сообщений (чат или почтовый клиент), где вы опрашиваете службу для получения новых сообщений. Одной из функций может быть установка числа в промежутке или отображение рычания, когда что-то происходит. Еще может быть обновление сетки. С помощью триггеров вам нужно будет запускать событие для каждого слушателя и «развертывать» переданные аргументы из eventData, с обратными вызовами это всего лишь один выстрел, а ваши слушатели - простые функции javascript с простым списком аргументов.

Обратные вызовы не совсем революционны, но они сделают код меньше и чище.

0 голосов
/ 10 ноября 2011

Я работаю над приложением с большой бизнес-логикой и по крайней мере 11 внешними сервисами. Это действительно помогает сохранять ясность, если вы можете написать свои собственные классы управления потоком и поведения, используя что-то вроде Callbacks вместо того, чтобы пытаться навязать свою волю отложенной реализации.

...