2017-03-17 116 views
1

我有一个变量oldBindings,它记录了Excel表的所有现有绑定。我已经根据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() 
} 

由于removeHandlerAsyncreleaseByIdAsynccallback而不是promise建,我需要callback来组织整个代码。有两件事我不确定:

1)in removeEventHandlers,will cb()总是在删除所有听众后执行?我怎么能确保?

2)我是否必须将addEventHandlers作为callbackremoveEventHandlers以确保其执行顺序?

回答

2

1)in removeEventHandlers,cb()总是会在删除所有监听器后执行?

号这将去除的开始后调用。但是,如果删除是异步的,则可以在删除完成之前调用它。

2)我是否必须将addEventHandlers作为removeEventHandlers的回调以确保其执行顺序?

是的,但不是你拥有的方式。你的方式就像是在做

removeEventHandlers(); 
addEventHandlers(); 

,因为你叫cbremoveEventHandlers年底,而无需等待任何东西到结束。

由于removeHandlerAsyncreleaseByIdAsync都建有callback而非promise,我需要callback来组织整个代码。

或者你可以给自己的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(); 
       } 
      }); 
     }); 
    } 
} 

但你有一个回调系统任何时候,你能答应,IFY它:

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); 
     }); 
    }); 
} 

或者你可以给自己一个通用的承诺,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); 
     }); 
    }); 
} 
+0

同意关于包装回调到一个承诺,如果它使你的代码逻辑更容易。 –

+0

真的很不错的教程...谢谢... – SoftTimur