是否可以在 context.sync 之前排队超过一个 context.load?

Is it possible to queue more than one context.load before context.sync?

我有一个 Word 段落对象的 paragraphObjects。我有一些段落和关键字索引的关键字范围。我还有一组要在文档中搜索和突出显示的关键字。

问题是 - 关键字搜索是线性的。我要loadsync每个关键字的搜索结果。因此,如果一次关键字搜索需要约 300 毫秒,则搜索 15 次将需要约 4500 秒。我想并行执行所有关键字搜索加载同步操作,所以我在 ~300 毫秒内得到所有结果,与关键字数组的大小无关。

代码示例如下:

let paragraphObjects = []
let keywordsObject = {
  "2": {
    "keywords": ["the", "which", "eye"]
  },
  "4": {
    "keywords": ["lorem", "ipsum"]
  },
  "9": {
    "keywords": ["hellow", "world", "foo", "bar"]
  }
}
let keywordRanges = []
let searchKeywordResults = []

Word.run((context) => {

  var paragraphs = context.document.body.paragraphs

  context.load(paragraphs, 'text, font, style');

  return context.sync().then(() => {
    for (var i = 0; i < paragraphs.items.length; i++) {
      paragraphObjects.push(paragraphs.items[i])
    }

    $.each(keywordsObject, (divId, divValue) => {
      $.each(divValue.keywords, (idx, keyword) => {
        var obj = { paragraphObject: pa[currentParaIndex], keyword: keyword }
        keywordRanges.push(obj)
      })
    })
  })
  .then(() => {
    if (keywordRanges.length > 0) {
      $.each(keywordRanges, (idx, obj) => {
        var paragraphObject = obj.paragraphObject
        var keyword = obj.keyword
        searchKeywordResults[idx] = paragraphObject.search(keyword, { matchWholeWord: true })
      })

      let highlight = async() => {
        for (let i = 0; i < searchKeywordResults.length; i++) {
          context.load(searchKeywordResults[i], 'text, font')
          await context.sync() // each iteration takes around 300 milliseconds. 
        }

        for (let i = 0; i < searchKeywordResults.length; i++) {
          for (let j = 0; j < searchKeywordResults[i].items.length; j++) {
            searchKeywordResults[i].items[j].font.highlightColor = highlightColorValue
          }
        }

        await context.sync()
        return
      }

      highlight()
    }
  })
})

我想用

替换此代码
for (let i = 0; i < searchKeywordResults.length; i++) {
    context.load(searchKeywordResults[i], 'text, font')
    await context.sync() 
}

有了这个

for (let i = 0; i < searchKeywordResults.length; i++) {
    context.load(searchKeywordResults[i], 'text, font')
}
await context.sync()

可能吗?

是的,将多个操作排队 sync 是 Office 2016+ API 批处理模型的重要组成部分。

举个很简单的Excel例子:

async function run() {
    try {
        await Excel.run(async (context) => {
            let sheet = context.workbook.worksheets.getItem("Sheet1");
            let a1 = sheet.getRange("A1");
            let b2 = sheet.getRange("B2");
            let c3 = sheet.getRange("C3");

            [a1, b2, c3].forEach(range => range.load("values"));

            await context.sync();

            [a1, b2, c3].forEach(range => console.log(range.values[0][0]));
        });
    }
    catch (error) {
        OfficeHelpers.UI.notify(error);
        OfficeHelpers.Utilities.log(error);
    }
}

所以,它绝对应该有效。当您尝试这样的操作时是否遇到错误?

FWIW(免责声明,我是该书的作者):我想您会在 "Building Office Add-in using Office.js" 一书中找到很多关于加载和批处理的有用信息,可在 https://leanpub.com/buildingofficeaddins/ 找到。特别是第 5 章——关于 Office.js 的基础知识——目前包括以下章节,全部用于代理对象、加载和同步: