如何使用jQuery Deferred with custom events?

我有两个抽象的进程(例如在js对象中使用不暴露其内部的暴露模块模式进行管理),它们在完成时触发自定义事件 。 我想在两个自定义事件都被触发时执行操作。

jQuery 1.5中新的Deferred逻辑似乎是一种管理它的理想方法,除了when()方法接受返回promise()的Deferred对象(或正常的js对象,但是当()立即完成而不是等等,这对我来说毫无用处)。

理想情况下,我想做的事情如下:

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

将这两种技术结合起来的最佳方法是什么?

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

现在,这些事件的事件处理程序只需要在捕获事件时对该事件调用“resolve”:

  df.resolve(event.type); 

每个处理程序报告自己的类型。 只有当您调用“watchEvents”时所请求的所有事件类型都已发生时,您在“df”上注册的处理函数实际上才会被调用。

在我看来,你可以做的另一件事是编写一个jQuery插件,初始化元素的Deferred对象,并将其存储在“.data()”属性中。 然后,您可以编写一些可供事件处理程序用来发信号的插件,以及其他用于为多事件序列注册处理程序的插件。 我觉得这很酷,但我需要花一些时间来思考它。