我在以下代码中遇到某种竞争状况,试图将HTTP请求的响应写入活动单元格。我已经阅读了Office.js中“ InvalidObjectPath”错误的一些可能的解决方案(我正在专门使用ScriptLab),但我认为我没有尝试在多个上下文中使用任何方法。

当前行为有时会起作用,但其他时候则不会有任何内容写入单元格。

var counter = 0;
$("#run").click(run);
async function run() {
    try {

        await Excel.run(async (ctx) => {
            var user;
            const sUrl = "https://jsonplaceholder.typicode.com/users/1";
            var client = new HttpClient();
            var range = ctx.workbook.getSelectedRange();
            counter++;
            client.get(sUrl, function (response) {
                var obj = JSON.parse(response);
                user = obj.username;
                range.values = [[user + counter]];
                ctx.sync();
            });
            await ctx.sync();
        });
    }
    catch (error) {
        OfficeHelpers.UI.notify(error);
        OfficeHelpers.Utilities.log(error);
    }
}

var HttpClient = function() {
    this.get = function(aUrl, aCallback) {
        var anHttpRequest = new XMLHttpRequest();
        anHttpRequest.onreadystatechange = function() {
            if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200)
                aCallback(anHttpRequest.responseText);
        }
        anHttpRequest.open( "GET", aUrl, true );
        anHttpRequest.send(null);
    }
}

最佳答案

问题是您不等待client.get的完成。这意味着[有时],Excel.run将在执行range内部的回调之前完成并“垃圾回收”(ish)某些对象(client.get)。

您可以通过多种方式解决此问题:


在执行Excel.run之前,请先调用Web服务。在此处的示例中(对于许多其他情况可能并不现实,但在此处),在进行网络调用之前,您实际上根本没有依赖文档中的任何内容。在那种情况下,根本不需要放在Excel.run内,您可以让Excel.run成为Web服务调用中的回调的一部分。
将您的Web服务呼叫包装在Promise中,以便可以等待。像这样:var HttpClient = function() { this.get = function(aUrl) { return new Promise(function (resolve, reject) { var anHttpRequest = new XMLHttpRequest(); anHttpRequest.onreadystatechange = function () { if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200) { resolve(anHttpRequest.responseText); } else { reject(anHttpRequest.statusText); } } anHttpRequest.open("GET", aUrl, true); anHttpRequest.send(null); }); }}


在我一直在写的有关使用Office.js构建Office加载项的书中,我描述了这两种方法(以及更多...):https://leanpub.com/buildingofficeaddins/。我在下面粘贴了一些相关书籍内容中的一些屏幕截图。

顺便说一句,我应该说,当您不想延迟sync时,获得选择只是少数几次,因为您想捕获短暂的时间点选择,而不是成为选择X的时间从现在开始,一旦网络通话成功。因此,这是少数情况下您可能想要插入一个额外的await context.sync()的情况之一,即使您在技术上不需要它。有关更多信息,请参见本书中的“ 5.8.2:何时同步”。

=====

宣传API:

javascript - 在Excel中使用Office.js的竞赛条件-LMLPHP

=====

关于承诺:

javascript - 在Excel中使用Office.js的竞赛条件-LMLPHP

=====

从实施细节部分:

javascript - 在Excel中使用Office.js的竞赛条件-LMLPHP

10-01 01:11