Я пишу некоторый JavaScript, который взаимодействует с плагином браузера (надстройка в FF, ActiveX в IE).Некоторые вызовы являются асинхронными и вызывают событие после завершения.В некоторых случаях мне нужно объединить вызовы в цепочку, но нужно дождаться завершения первого вызова, прежде чем начинать второй.Например:
При вызове для подключения устройства сначала необходимо проверить, подключено ли уже устройство, и отключить его.Таким образом, вызовы были бы:
pluginObject.disconnectDevice(deviceKey);
pluginObject.connectDevice(deviceKey, backingInfo);
Просто вызвать их прямо так, как это будет невозможно, потому что соединение инициируется до того, как разъединение действительно завершено, и плагин не может это обработать.
У меня уже настроены слушатели, и я могу сделать что-то вроде:
function handleConnectionChange(connectionState, /* ... */, doReconnect) {
if (connectionState === state.disconnected && doReconnect) {
pluginObject.connectDevice(deviceKey, backingInfo);
}
}
Но я бы на самом деле хотел бы более общий подход - тот, который можно использовать повторно, даже с другим наборомскованные события. .Это достаточно просто в данном конкретном случае, но даже это немного небрежно.Я добавил информационную логику переподключения в обработчик событий соединения, и я мог легко видеть, как условное сцепление выходит из-под контроля, когда все сделано следующим образом.
Существуют ли какие-либо библиотеки, которые занимаются этим типом рабочего процесса?Я посмотрел на отложенные вещи jQuery, и у них есть цепочка, которую я хочу, но на самом деле она не подходит для обратных вызовов.StateCharts от Sproutcore выглядит интересно, но опять же, похоже, нет возможности перерабатывать уже асинхронный поток.
Обновление: решение Благодаря некоторым указателям из Густаво, я пошел сподход обертывания вызовов плагинов, чтобы заставить их использовать объекты jQuery Deferred:
var connectDevice = function(deviceKey, backingInfo) {
var deferred = $.Deferred();
var connectHandler = function(event) {
// unregister connectHandler
if (event.connectionState === ERROR) {
showAlert("Error connecting device", event.message);
deferred.reject();
} else {
showAlert("Device connected", event.message);
deferred.resolve();
}
};
// register connectHandler
pluginObject.connectDevice(deviceKey, backingInfo);
return deferred.promise();
};
Если я создаю подобную оболочку для отключения, теперь я могу связывать вызовы методов (или не в зависимости от потока):
if (forceDisconnect) {
disconnectDevice(deviceKey).done(connectDevice(deviceKey, backingType));
} else {
connectDevice(deviceKey, backingType);
}
Я также могу запустить цепочку с помощью connectDevice или добавить другую функцию в поток forceDisconnect и т. Д.