Spec-Zone.ru › jQuery

jQuery.Callbacks()

jQuery.Callbacks( flags )Возвращает: Callbacks

Описание: Объект списка обратных вызовов общего назначения, предоставляющий мощный способ управления списками обратных вызовов.

  • версия добавлена: 1.7jQuery.Callbacks( flags )

    • flags
      Тип: Строка
      Необязательный список флагов, разделённых пробелами, которые изменяют поведение списка обратных вызовов.

Функция $.Callbacks() внутренне используется для обеспечения базовой функциональности компонентов jQuery $.ajax() и $.Deferred(). Её можно использовать в качестве аналогичной базы для определения функциональности новых компонентов.

$.Callbacks() поддерживает ряд методов, включая callbacks.add(), callbacks.remove(), callbacks.fire() и callbacks.disable().

Начало работы

Ниже приведены два примера методов с именами fn1 и fn2:

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

Их можно добавить в качестве обратных вызовов в список $.Callbacks и вызвать следующим образом:

var callbacks = $.Callbacks();
callbacks.add( fn1 );
 
// Outputs: foo!
callbacks.fire( "foo!" );
 
callbacks.add( fn2 );
 
// Outputs: bar!, fn2 says: bar!
callbacks.fire( "bar!" );

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

Выше использовались два конкретных метода: .add() и .fire(). Метод .add() поддерживает добавление новых обратных вызовов в список обратных вызовов, а метод .fire() выполняет добавленные функции и предоставляет способ передачи аргументов для обработки обратными вызовами в том же списке.

Ещё один метод, поддерживаемый $.Callbacks, это .remove(), который позволяет удалить определённый обратный вызов из списка обратных вызовов. Вот практический пример использования .remove():

var callbacks = $.Callbacks();
callbacks.add( fn1 );
 
// Outputs: foo!
callbacks.fire( "foo!" );
 
callbacks.add( fn2 );
 
// Outputs: bar!, fn2 says: bar!
callbacks.fire( "bar!" );
 
callbacks.remove( fn2 );
 
// Only outputs foobar, as fn2 has been removed.
callbacks.fire( "foobar" );

Поддерживаемые флаги

Аргумент flags — это необязательный аргумент к $.Callbacks(), представляющий собой список разделённых пробелами строк, которые изменяют поведение списка обратных вызовов (например, $.Callbacks( "unique stopOnFalse" )).

Возможные флаги:

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

$.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() поддерживает список флагов, а не только один, установка нескольких флагов имеет кумулятивный эффект, аналогичный «&&». Это означает, что можно комбинировать флаги, чтобы создать списки обратных вызовов, которые, например, являются как уникальными, так и обеспечивают, что если список уже был вызван, добавление дополнительных обратных вызовов вызовет его с последним значением вызова (то есть $.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
*/

Комбинации флагов с $.Callbacks() используются внутри jQuery для функций .done() и .fail() в Deferred — обе из которых используют $.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 и Pub/Sub

Основная идея pub/sub (Publish/Subscribe, или паттерн наблюдателя) — это содействие слабой связанности в приложениях. Вместо того, чтобы отдельные объекты вызывали методы других объектов, объект вместо этого подписывается на определённую задачу или действие другого объекта и получает уведомление при её выполнении. Наблюдатели также называются подписчиками, а объект, за которым ведётся наблюдение, называется издателем (или субъектом). Издатели уведомляют подписчиков о событиях.

Для демонстрации возможностей создания компонентов $.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( "it's been published!" );

© The jQuery Foundation and other contributors
Licensed under the MIT License.
https://api.jquery.com/jQuery.Callbacks

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API