Как использовать jQuery Отложено с пользовательскими событиями? - PullRequest
22 голосов
/ 15 февраля 2011

У меня есть два абстрактных процесса (например, управляемых в объектах js с использованием шаблона модуля раскрытия, которые не раскрывают свои внутренние компоненты), которые запускают пользовательских событий , когда они завершаются. Я хочу выполнить действие, когда оба пользовательских события сработали.

Новая логика Deferred в jQuery 1.5 кажется идеальным способом управления этим, за исключением того, что метод when () принимает отложенные объекты, которые возвращают обещание () (или обычные объекты js но тогда, когда () завершается немедленно вместо ожидания, что для меня бесполезно).

В идеале я хотел бы сделать что-то вроде:

//execute when both customevent1 and customevent2 have been fired
$.when('customevent1 customevent2').done(function(){
  //do something
});

Как лучше всего сочетать эти две техники?

Ответы [ 2 ]

40 голосов
/ 16 февраля 2011

http://jsfiddle.net/ch47n/

Я создал небольшой плагин, который создает новый метод jQuery.fn.when.

Синтаксис:

jQuery( "whatever" ).when( "event1 event2..." ).done( callback );

Он широко использует jQuery.when () для внутреннего использования и гарантирует, что все события были запущены на всех элементах в коллекции до разрешения.


Фактический код плагина ниже:

( function( $ ) {

    $.fn.when = function( events ) {

        var deferred, $element, elemIndex, eventIndex;

        // Get the list of events
        events = events.split( /\s+/g );

        // We will store one deferred per event and per element
        var deferreds = [];

        // For each element
        for( elemIndex = 0; elemIndex < this.length; elemIndex++ ) {
            $element = $( this[ elemIndex ] );
            // For each event
            for ( eventIndex = 0; eventIndex < events.length; eventIndex++ ) {
                // Store a Deferred...
                deferreds.push(( deferred = $.Deferred() ));
                // ... that is resolved when the event is fired on this element
                $element.one( events[ eventIndex ], deferred.resolve );
            }
        }

        // Return a promise resolved once all events fired on all elements
        return $.when.apply( null, deferreds );
    };

} )( jQuery );
12 голосов
/ 15 февраля 2011

Вы можете иметь обработчики событий для «customevent1» и «customevent2», каждый из которых сигнализирует об «отложенном» экземпляре при запуске.Вы можете использовать «$ .when ()», чтобы затем объединить эти два в одно, и именно здесь вы запускаете обработчик только после того, как оба пользовательских события сработали.

var df1 = $.Deferred(), df2 = $.Deferred();
$('whatever').bind('customevent1', function() {
  // code code code
  df1.resolve();
}).bind('customevent2', function() {
  // code code code
  df2.resolve();
});

var whenBoth = $.when(df1, df2);

whenBoth.then(function() {
  // code to run after both "customevent1"
  // and "customevent2" have fired
});

Старый ответ, здесь для полноты картины

Вы можете создать свой собственный Отложенный объект, который отслеживает два условия и запускает «разрешение», когда оба установлены:

function watchEvents() {
  var df = $.Deferred();

  var flags = {};
  $.each(Array.prototype.slice.call(arguments, 0), function() {
    flags[this] = false;
  });

  var realResolve = df.resolve.bind(df);
  df.resolve = function(eventName) {
    flags[eventName] = true;
    for (var ev in flags) if (flags[ev] === false) return;
    realResolve();
  };

  return df;
}

СейчасВы можете вызвать эту функцию:

var df = watchEvents("customevent1", "customevent2");

И теперь ваши обработчики событий для этих событий просто должны вызвать «resolv» для этой вещи, когда они перехватывают события:

    df.resolve(event.type);

Каждый обработчиксообщает свой собственный тип.Только когда все типы событий, запрошенные при вызове «watchEvents», произойдут, вызовут те функции-обработчики, которые вы зарегистрировали в «df».

Мне приходит в голову, что вы могли бы написать еще одну вещь:плагин jQuery, который инициализирует отложенный объект для элементов и сохраняет его в свойстве ".data ()".Затем вы можете написать еще несколько плагинов, которые могут использоваться обработчиками событий, чтобы сигнализировать о себе, и другие плагины, чтобы регистрировать обработчики для последовательностей нескольких событий.Думаю, это было бы круто, но мне нужно потратить некоторое время на обдумывание.

...