我有一个变量oldBindings
,它记录了 Excel 表的所有现有绑定(bind)。我基于 oldBindings
构建了 BindingDataChanged
监听器。因此,当 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
构建的,我需要组织整个代码与回调
。有两件事我不确定:
1) 在removeEventHandlers
中,cb()
是否总是在删除所有监听器后执行?我怎样才能确保这一点?
2) 我是否必须将 addEventHandlers
作为 removeEventHandlers
的回调
以确保其执行顺序?
最佳答案
1) in
removeEventHandlers
, will cb() ALWAYS be executed after the removal of all the listeners?
没有。它将在删除启动后被调用。但如果删除是异步的,则可能会在删除完成之前调用它。
2) Do I have to make
addEventHandlers
as a callback ofremoveEventHandlers
to ensure their execution order?
是的,但不是你的方式。你所拥有的方式就像做
removeEventHandlers();
addEventHandlers();
因为您在 removeEventHandlers
末尾调用 cb
,而无需等待任何操作完成。
As
removeHandlerAsync
andreleaseByIdAsync
are built withcallback
rather thanpromise
, I need to organise the whole code withcallback
.
或者你可以给自己提供它们的 Promise 版本。稍后会详细介绍。
使用非 Promise 回调方法,以确保在所有工作完成后从 removeEventHandlers
调用 cb
,请记住您期望的回调次数并等待在调用 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();
}
});
});
}
}
但是只要你有回调系统,你就可以 Promise 化它:
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);
});
});
}
或者您可以为自己提供一个通用的 Promise-ifier,用于返回 AsyncResult
的任何异步操作:
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);
});
});
}
关于javascript - 循环中的异步回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42848775/