我在以下代码中遇到某种竞争条件,我试图将HTTP请求的响应写入活动单元格。我已经阅读了" InvalidObjectPath"的一些可能的解决方案。来自Office.js的错误(我特意使用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);
}
}
答案 0 :(得分:0)
问题是您没有等待client.get
的完成。这意味着[某些时候],Excel.run
将完成并且“垃圾收集”(ish)执行range
内部回调之前的一些对象(client.get
)
您可以通过多种方式解决问题:
在执行Excel.run
之前,请先调用Web服务。在这里的示例中(对于许多其他场景可能不太现实,但它就在这里),在进行Web调用之前,您实际上并不依赖文档中的任何内容。在这种情况下,根本不需要在Excel.run
内,您可以让Excel.run
成为Web服务调用回调的一部分。
将您的网络服务电话包含在承诺中,以便等待它。这样的事情:
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 :
=====
关于Promises :
=====
从实施细节部分: