我有两个抽象的进程(例如在js对象中使用不暴露其内部的暴露模块模式进行管理)在完成时触发custom events。我希望在两个自定义事件都被触发时执行操作。
jQuery 1.5中的新Deferred逻辑似乎是理想的管理方式,除了when()方法接受返回promise()的deferred对象(或普通的js对象,但是when()立即完成而不是等待,这对我来说毫无用处。)
理想情况下,我想做类似的事情:
//execute when both customevent1 and customevent2 have been fired
$.when('customevent1 customevent2').done(function(){
//do something
});
将这两种技术结合起来的最佳方式是什么?
答案 0 :(得分:40)
我创建了一个小插件,创建了一个新的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 );
答案 1 :(得分: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
});
旧答案,这里是为了完整起见
您可以创建自己的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");
现在,这些事件的事件处理程序只需要在事件发生时调用“解决”事件:
df.resolve(event.type);
每个处理程序报告自己的类型。只有当您调用“watchEvents”时请求的所有事件类型都发生时,您在“df”上注册的处理函数实际上才会被调用。
我觉得你可以做的另一件事就是编写一个jQuery插件来初始化元素的Deferred对象,并将它存储在“.data()”属性中。然后,您可以编写一些可供事件处理程序用来发信号的插件,以及其他用于为多事件序列注册处理程序的插件。我觉得这很酷,但我需要花一些时间来思考它。