javascript 如何将 jQuery Deferred 与自定义事件一起使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5009194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use jQuery Deferred with custom events?
提问by Adam Flynn
I have two abstracted processes (e.g. managed within js objects using the revealing module pattern that do not expose their internals) that fire custom eventswhen they complete. I want to perform an action when both custom events have fired.
我有两个抽象进程(例如,在 js 对象中使用不公开其内部结构的揭示模块模式进行管理),它们在完成时触发自定义事件。我想在两个自定义事件都触发时执行一个操作。
The new Deferredlogic in jQuery 1.5 seems like it would be an ideal way to manage this, except that the when() method takes Deferred objects that return a promise() (or normal js objects, but then when() completes immediately instead of waiting, which is useless to me).
jQuery 1.5 中新的Deferred逻辑似乎是一种理想的管理方式,除了 when() 方法采用返回 promise() 的 Deferred 对象(或普通的 js 对象,但是 when() 立即完成而不是等待,这对我来说没用)。
Ideally I would like to do something like:
理想情况下,我想做类似的事情:
//execute when both customevent1 and customevent2 have been fired
$.when('customevent1 customevent2').done(function(){
//do something
});
What would be the best way to marry these two techniques?
结合这两种技术的最佳方式是什么?
回答by Julian Aubourg
I created a small plugin that creates a new jQuery.fn.when method.
我创建了一个小插件来创建一个新的 jQuery.fn.when 方法。
Syntax is:
语法是:
jQuery( "whatever" ).when( "event1 event2..." ).done( callback );
It uses jQuery.when() extensively internally and ensures that all events have been triggered on all elements in the collection before resolving.
它在内部广泛使用 jQuery.when() 并确保在解析之前已在集合中的所有元素上触发所有事件。
Actual plugin code below:
实际插件代码如下:
( 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 );
回答by Pointy
You can have the event handlers for "customevent1" and "customevent2" each signal a "Deferred" instance when they fire. You can use "$.when()" then to combine those two into one, and that's where you put the handler to fire only after both custom events have fired.
您可以让“customevent1”和“customevent2”的事件处理程序在它们触发时分别发出“Deferred”实例信号。您可以使用“$.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
});
Old answer, here for completeness sake
旧答案,这里是为了完整起见
You can make your own Deferred object that keeps track of the two conditions and fires "resolve" when both are set:
您可以创建自己的 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;
}
Now you can call that function:
现在您可以调用该函数:
var df = watchEvents("customevent1", "customevent2");
And now your event handlers for those events just need to call "resolve" on that thing when they catch the events:
现在,这些事件的事件处理程序只需要在捕获事件时调用“resolve”即可:
df.resolve(event.type);
Each handler reports its own type. Only when all of the event types requested when you called "watchEvents" have happened will the handler functions you register on "df" actually get called.
每个处理程序报告自己的类型。只有当您调用“watchEvents”时请求的所有事件类型都发生时,您在“df”上注册的处理函数才会真正被调用。
It occurs to me that another thing you could do would be to write a jQuery plugin that initializes a Deferred object for elements, and stores it in a ".data()" property. You could then write some more plugins that can be used by event handlers to signal themselves, and other plugins to register handlers for multi-event sequences. That'd be pretty cool, I think, but I need to spend some time pondering it.
在我看来,您可以做的另一件事是编写一个 jQuery 插件,为元素初始化一个延迟对象,并将其存储在“.data()”属性中。然后,您可以编写更多插件,事件处理程序可以使用这些插件来向自己发出信号,并编写其他插件来为多事件序列注册处理程序。我想那会很酷,但我需要花一些时间思考它。

