2011-02-15 61 views
22

我有兩個抽象的進程(例如,使用暴露模塊模式的js對象內部管理,不暴露它們的內部),它們在完成時觸發custom events。我想在自定義事件發起時執行操作。除了when()方法需要Deferred對象返回一個promise()(或者普通的js對象,但是之後的when()方法)之外,jQuery 1.5中新的Deferred邏輯似乎是一種理想的管理方法。立即完成而不是等待,這對我毫無用處)。如何使用jQuery推遲使用自定義事件?

理想我想這樣做:

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

什麼會嫁給這兩種技術的最佳方法是什麼?

回答

40

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

您可以讓「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"); 

而現在這些事件的事件處理程序只需要調用「解決」上的事情時,他們抓住的事件:

df.resolve(event.type); 

每個處理程序報告了自己的類型。只有當您調用「watchEvents」時發生的所有事件類型都會發生,您在「df」上註冊的處理函數纔會被調用。

它發生在我身上,你可以做的另一件事是編寫一個jQuery插件,爲元素初始化Deferred對象,並將其存儲在「.data()」屬性中。然後,您可以編寫一些可供事件處理程序用來發信號的插件,以及其他用於註冊多事件序列的處理程序的插件。我認爲這很酷,但我需要花一些時間思考它。

+0

是 「df.reserve」 上面一個錯字?我無法在jQuery Deferred API文檔中找到保留屬性。如果你可以提供一個鏈接,如果它存在,我將不勝感激。 – 2011-02-15 21:13:47

+0

是的當它 - 當我的意思是「解決」時,我繼續打字「保留」! – Pointy 2011-02-15 21:14:54