我在开发 Office .js Word 加载项方面取得了很大的成功。外接程序的常见任务之一是搜索和替换,这需要由外接程序中的多个操作按钮使用。因此,我想创建一个函数,将搜索和替换任务分开,这样我就可以避免错误并使代码更加模块化。我在尝试使用 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');
}
}
我已经尝试了一些变化,但我确定我错过了一些基本的东西。谁能帮我找出处理需要访问父函数上下文的子例程的正确方法?
你的代码正在破坏承诺链。您的replaceInRange
方法中有一个异步调用来context.sync
,但replaceInRange
本身并没有等待,因此一旦它开始执行,执行引擎就会移动到调用replaceInRange
下方的行,这是另一个context.sync
。但是最后一个context.sync
将在字符串替换代码运行之前完成,然后Word.run
将完成。
尝试在调用replaceInRange
前面放置一个await
关键字,如下所示:
await this.replaceInRange(context, range, query, replacement, {});
我注意到的其他几件事:
不需要
Word.run
中的第一个context.sync
。您不会将任何参数传递给
load()
方法。执行此操作时,将加载所有标量属性。这是不必要的性能影响。您只需要加载text
属性即可执行insertText
。使用results.load('text');
Word.run
本身是异步的,因此在调用它时可能应该使用await
关键字。您可以在没有await
的情况下逃脱,因为您的父方法在 Word.run 执行后不调用任何内容,但是如果您曾经修改过该方法以便在Word.run
之后调用更多内容,如果您不等待Word.run
,则在Word.run
完成之前将开始执行更多内容。
有一本关于 Office 外接程序的好书,其中包含有关这些主题的大量信息,包括承诺链:构建 Office 外接程序。它花费了一些东西,但这是值得的。在你问之前,这不是我的书,我从它的销售中没有任何收获。