环境:Mac 10.12.6、Word 2016 (16.11.1)、@microsoft/office-js "^1.1.4"
我想知道在如何使用 CustomXMLParts 以最大限度地提高读/写性能方面是否有任何指南或最佳实践,或者是否有一种“理想”的方式来为 XML 部件中的数据建模以实现相同目的。
我正在编写一个加载项,因此我需要在可见文档之外保留一些数据,但在 docx 文件内部。
例如,我正在存储一张发票列表(可能是 100-200 张发票),每张发票都有典型的结构化数据(姓名、ID、日期、工作项列表)和一个最多可包含 5 个自由式注释部分-10kb 的文本、说明等。
我获取这些发票,在 Word 文档中呈现其中的一些,然后在任务窗格中对其余数据进行一些可视化分析 - 用户可以在其中将注释写回(并保存)到自定义 XML 部件(到该发票中)他们正在看的)。
现在......这是我有点困惑的地方......我不确定是否最好将每张发票作为单独的 CustomXMLPart 存储在文件中(例如,每张发票 1 个 XML 文件),或者是否最好存储所有发票在单个大型 CustomXMLPart 中,或者如果有中间立场(例如,每个 XML 部分 10 个发票)。如前所述,用例是读取所有发票,然后偶尔更新可能 10-20% 的发票中的数据。
现在,我为每个 XML 部件存储 1 张发票,当我加载我的插件并进行批量读取以将所有内容放入内存时,每张发票平均需要 250-500 毫秒才能并行读取它们(所以, 250-500ms * 100-200 张发票)。因此,它需要更长的时间(2-3 倍长)。使用 performance.now() 测试,使用挂钟计时验证。
这似乎是一个很长的时间,所以我不知道我是否做错了什么 - 或者这是否只是打开并从这些文件中提取数据所需的时间?
// Sequential example - excluding error handling and type-safety
// Parallel equivalent is essentially a Promise.all with a .map
// Approx 50ms
let result = await this.xmlPartsHelper.getByNamespaceAsync(...);
for (const item of result.value) {
// Approx 150-200ms
result = await this.xmlPartsHelper.getByIdAsync(item.id);
// Approx 150-200ms
result = await this.xmlPartsHelper.getXmlAsync(result.value);
// Approx 5ms
const invoice = this.mapper.reverseMap(result.value);
invoices.push(invoice)
}
我用 Promises 手动包装了 Office-JS 回调,但我已经使用 async/await、then/catch 和 office-js 回调测试了这个示例——结果都大致相同。
public getByNamespaceAsync(namespace: string): Promise<Office.AsyncResult> {
return new Promise<Office.AsyncResult>((resolve, reject) => {
Office.context.document.customXmlParts.getByNamespaceAsync(namespace, (result: Office.AsyncResult) => {
return resolve(result);
});
});
}
public getByIdAsync(id: string): Promise<Office.AsyncResult> {
return new Promise<Office.AsyncResult>((resolve, reject) => {
Office.context.document.customXmlParts.getByIdAsync(id, (result: Office.AsyncResult) => {
return resolve(result);
});
});
}
public getXmlAsync(xmlPart: Office.CustomXmlPart): Promise<Office.AsyncResult> {
return new Promise<Office.AsyncResult>((resolve, reject) => {
xmlPart.getXmlAsync((result: Office.AsyncResult) => {
return resolve(result);
});
});
}
更新
我不完全理解的一个难题是 CustomXMLNode - 也许这会有所帮助。似乎有专门在 CustomXMLPart ( https://dev.office.com/reference/add-ins/shared/customxmlnode.customxmlnode ) 的节点中获取/设置数据的方法 - 所以也许这就是中间选项,我可以将所有发票放入一个 CustomXMLPart 中(这样我只会为单个 CustomXMLPart 受到文件系统的影响),然后我可以有选择地更新该 CustomXMLPart 的各个部分(使用 CustomXMLNode),这样我就不仅仅是在做完全删除并重新保存?