我有一个变量BindingDataChanged
,它记录了Excel表的所有现有绑定。我基于oldBindings
构建了newBindings
个侦听器。因此,当oldBindings
出现时,我需要删除链接到newBindings
的所有旧侦听器,并根据var oldBindings = ["myBind1", "myBind2"]; // can be updated by other functions
function updateEventHandlers(newBindings) {
removeEventHandlers(oldBindings, function () {
addEventHandlers(newBindings)
})
}
function removeEventHandlers(oldBindings, cb) {
for (var i = 0; i < oldBindings.length; i++) {
Office.select("binding#"+oldBindings[i]).removeHandlerAsync(Office.EventType.BindingDataChanged, function (asyncResult) {
Office.context.document.bindings.releaseByIdAsync(oldBindings[i], function () {});
});
}
cb()
}
添加新的侦听器。目前,我已经编写了以下代码:
removeHandlerAsync
由于releaseByIdAsync
和callback
是使用promise
而不是callback
构建的,因此我需要使用removeEventHandlers
整理整个代码。我不确定有两件事:
1)在cb()
中,addEventHandlers
总是会在删除所有听众后执行吗?我怎么能确保这个?
2)我是否必须callback
作为removeEventHandlers
ImportError: DLL load failed: The specified module could not be found
来确保执行顺序?
答案 0 :(得分:2)
1)在
removeEventHandlers
中,cb()是否会在删除所有侦听器后执行?
没有。它将在删除的启动之后被调用。但是如果删除是异步的,则可以在删除完成之前调用它。
2)我是否必须将
addEventHandlers
作为removeEventHandlers
的回调以确保其执行顺序?
是的,但不是你的方式。你的方式就像做
removeEventHandlers();
addEventHandlers();
因为您在cb
结束时致电removeEventHandlers
而无需等待任何事情完成。
由于
removeHandlerAsync
和releaseByIdAsync
是使用callback
而非promise
构建的,因此我需要使用callback
整理整个代码。
或者你可以给自己的Promise版本。稍等一下。
使用非Promise回调方法,确保在完成所有工作后从cb
致电removeEventHandlers
,记住您预计会有多少回调,并等到有多少回调在致电cb
之前:
var oldBindings = ["myBind1", "myBind2"]; // can be updated by other functions
function updateEventHandlers(newBindings) {
removeEventHandlers(oldBindings, function() {
addEventHandlers(newBindings);
});
}
function removeEventHandlers(oldBindings, cb) {
var waitingFor = oldBindings.length;
for (var i = 0; i < oldBindings.length; i++) {
Office.select("binding#"+oldBindings[i]).removeHandlerAsync(Office.EventType.BindingDataChanged, function (asyncResult) {
Office.context.document.bindings.releaseByIdAsync(oldBindings[i], function () {
if (--waitingFor == 0) {
cb();
}
});
});
}
}
但是,只要你有一个回调系统,你就可以承诺 - 如果它:
function removeHandlerPromise(obj, eventType) {
return new Promise(function(resolve, reject) {
obj.removeHandlerAsync(eventType, function(asyncResult) {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
reject(asyncResult.error);
} else {
resolve(asyncResult.value);
}
});
});
}
function releaseByIdPromise(obj, value) {
return new Promise(function(resolve, reject) {
obj.releaseByIdAsync(value, function(asyncResult) {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
reject(asyncResult.error);
} else {
resolve(asyncResult.value);
}
});
});
}
然后,你可以这样做:
var oldBindings = ["myBind1", "myBind2"]; // can be updated by other functions
function updateEventHandlers(newBindings) {
removeEventHandlers(oldBindings).then(function() {
addEventHandlers(newBindings);
});
}
function removeEventHandlers(oldBindings) {
return Promise.all(oldBindings.map(function(binding) {
return removeHandlerPromise(Office.select("binding#"+binding), Office.EventType.BindingDataChanged).then(function() {
return releaseByIdPromise(Office.context.document.bindings, binding);
});
});
}
或者,您可以为任何返回AsyncResult
的异步操作提供一个通用的Promise-ifier:
function promisify(obj, method) {
var args = Array.prototype.slice.call(arguments, 2);
return new Promise(function(resolve, reject) {
args.push(function(asyncResult) {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
reject(asyncResult.error);
} else {
resolve(asyncResult.value);
}
});
obj[method].apply(obj, args);
});
}
然后,你可以这样做:
var oldBindings = ["myBind1", "myBind2"]; // can be updated by other functions
function updateEventHandlers(newBindings) {
removeEventHandlers(oldBindings).then(function() {
addEventHandlers(newBindings);
});
}
function removeEventHandlers(oldBindings) {
return Promise.all(oldBindings.map(function(binding) {
return promisify(Office.select("binding#"+binding), "removeHandlerAsync", Office.EventType.BindingDataChanged).then(function() {
return promisify(Office.context.document.bindings, "releaseByIdAsync", binding);
});
});
}