【发布时间】:2011-06-15 22:05:57
【问题描述】:
我正在编写一些与浏览器插件交互的 JavaScript(Firefox 中的插件,IE 中的 ActiveX)。一些调用是异步的,并在完成时触发一个事件。在某些情况下,我需要将调用链接在一起,但需要等待第一个调用完成,然后再发起第二个调用。例如:
附加设备的调用需要首先检查设备是否已附加,然后断开连接。所以电话是:
pluginObject.disconnectDevice(deviceKey);
pluginObject.connectDevice(deviceKey, backingInfo);
像这样直接调用它们会失败,因为在断开连接实际完成之前启动了连接,而插件无法处理。
我已经设置了监听器,我可以执行以下操作:
function handleConnectionChange(connectionState, /* ... */, doReconnect) {
if (connectionState === state.disconnected && doReconnect) {
pluginObject.connectDevice(deviceKey, backingInfo);
}
}
但我实际上想要一种更通用的方法——即使有一组不同的链式事件也可以重复使用。。在这个特定的例子中,这很简单,但即使这样也有点草率。我已将重新连接信息逻辑添加到连接事件处理程序中,当这样完成时,我可以很容易地看到条件链失控。
是否有任何库可以处理这种工作流程?我查看了 jQuery 的延迟内容,它具有我想要的链接,但它似乎并不适合回调。 Sproutcore 的 StateCharts 看起来很有趣,但似乎又无法重新处理已经异步的流程。
更新:解决方案 感谢 Gustavo 提供的一些建议,我采用了包装插件调用以使它们利用 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流中添加另一个函数等等。
【问题讨论】:
-
你如何设置那个监听器?只是
pluginObject.handleConnectionChange = function() {}? -
那我的回答应该可以了!
标签: javascript synchronization dom-events