Вот как бы я это сделал. Этот подход является общим, который дает вам больше гибкости и повторного использования, а также избегает объединения и использования глобальных переменных.
var makeEventHandler = function(eventMinimum, callback) {
var data = [];
var eventCount = 0;
var eventIndex = -1;
return function() {
// Create a local copy to avoid issues with closure in the inner-most function
var ei = ++eventIndex;
return function() {
// Convert arguments into an array
data[ei] = Array.prototype.slice.call(arguments);
// If the minimum event count has not be reached, return
if ( ++eventCount < eventMinimum ) {
return;
}
// The minimum event count has been reached, execute the original callback
callback(data);
};
};
};
Общее использование:
// Make a multiple event handler that will wait for 3 events
var multipleEventHandler = makeMultipleEventHandler(3, function(data) {
// This is the callback that gets called after the third event
console.log(data);
});
multipleEventHandler()(1,2,3);
var t = multipleEventHandler();
setTimeout(function() {t("some string");}, 1000);
multipleEventHandler()({a: 4, b: 5, c: 6});
Вывод из обратного вызова (сжатый Firebug):
[[1, 2, 3], ["some string"], [Object { a=4, more...}]]
Обратите внимание, что порядок data
в последнем обратном вызове соответствует порядку вызывающих событий, даже если второе «событие» выполняется после третьего.
Чтобы использовать это в контексте ваших запросов Ajax:
var onBothComplete = makeMultipleEventHandler(2, function(data) {
// Do something
...
});
new Ajax.Request(url1, {onComplete: onBothComplete()});
new Ajax.Request(url2, {onComplete: onBothComplete()});
Редактировать: я обновил функцию, чтобы заставить data
всегда поддерживать асинхронно полученные данные о событиях в синхронно выполняемом порядке (предыдущее предупреждение больше не существует).