Как использовать jQuery Отложено с пользовательскими событиями?

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

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

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

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

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

2 ответа

Решение

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 );

У вас могут быть обработчики событий для "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
});

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

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

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, который инициализирует объект Deferred для элементов и сохраняет его в свойстве ".data()". Затем вы можете написать еще несколько плагинов, которые могут использоваться обработчиками событий, чтобы сигнализировать о себе, и другие плагины, чтобы регистрировать обработчики для последовательностей нескольких событий. Это было бы здорово, я думаю, но мне нужно потратить некоторое время на обдумывание этого.

Другие вопросы по тегам