如何使用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 });
将这两种技术结合起来的最佳方法是什么?
我创建了一个小插件,创建了一个新的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()”属性中。 然后,您可以编写一些可供事件处理程序用来发信号的插件,以及其他用于为多事件序列注册处理程序的插件。 我觉得这很酷,但我需要花一些时间来思考它。