我在为脚本开发Office.js加载项方面取得了很大的成功。加载项的常见任务之一是搜索和替换,这需要由加载项中的多个操作按钮使用。因此,我想创建一个将搜索和替换任务分开的功能,这样我就可以避免错误并使代码更加模块化。我试图用Office.js异步执行模型来解决这个问题。
此代码有效(作为React类的方法):
replaceX() {
console.log("replaceX");
window.Word.run(async (context: any) => {
const range = context.document.getSelection();
await context.sync();
var query = "X";
var replacement = "gabagool";
var results = range.search(query);
results.load();
await context.sync();
for (var i=0; i<results.items.length; i++) {
results.items[i].insertText(replacement,'Replace');
}
await context.sync();
});
}
但是这段代码失败了:
replaceX() {
console.log("replaceX");
window.Word.run(async (context: any) => {
const range = context.document.getSelection();
await context.sync();
var query = "X";
var replacement = "gabagool";
this.replaceInRange(context, range, query, replacement, {});
await context.sync();
});
}
async replaceInRange(context:any, range:any, query:String, replacement:String, searchOptions:any) {
console.log('replaceInRange');
var results = range.search(query, searchOptions);
results.load();
await context.sync();
for (var i=0; i<results.items.length; i++) {
results.items[i].insertText(replacement,'Replace');
}
}
我尝试了一些变化,但我确定我遗漏了一些基本的东西。任何人都可以帮我找出处理需要访问父函数上下文的子程序的正确方法吗?
答案 0 :(得分:2)
您的代码正在破坏Promise链。你的replaceInRange
方法在context.sync
内有一个异步调用,但replaceInRange
本身并不等待,所以只要它开始执行,执行引擎就会移动到下面的行。致电replaceInRange
,这是另一个context.sync
。但是,在字符串替换代码运行之前,最后context.sync
将完成,然后Word.run
将完成。
尝试将await
关键字放在replaceInRange
的调用前面,如下所示:
await this.replaceInRange(context, range, query, replacement, {});
我注意到的其他一些事情:
不需要context.sync
中的第一个Word.run
。
您没有将任何参数传递给load()
方法。执行此操作时,将加载所有标量属性。这是不必要的性能损失。您只需加载text
属性即可insertText
。使用results.load('text');
Word.run
本身是异步的,因此您在调用它时可能应该使用await
关键字。您可以在没有await
的情况下离开,因为您的父方法在Word.run执行后不会调用任何内容,但是如果您修改了方法以便在Word.run
之后调用更多内容,则会发生更多事情如果您没有等待Word.run
,则在Word.run
完成之前执行。
这是一本关于Office加载项的好书,其中包含许多有关这些主题的信息,包括Promise链:Building Office Add-ins。它花费了一些东西,但它是值得的。在你问之前,这不是我的书,我从销售中得不到任何东西。