Javascript 在Excel中使用Office.js的竞赛条件
在下面的代码中,我遇到了某种竞争条件,我试图将HTTP请求的响应写入活动单元格。我已经从Office.js中阅读了一些解决“InvalidObjectPath”错误的可能方法(我专门使用ScriptLab),但我不认为我试图在多个上下文中使用任何方法 当前行为有时有效,但其他时候不会向单元格写入任何内容Javascript 在Excel中使用Office.js的竞赛条件,javascript,async-await,office-js,Javascript,Async Await,Office Js,在下面的代码中,我遇到了某种竞争条件,我试图将HTTP请求的响应写入活动单元格。我已经从Office.js中阅读了一些解决“InvalidObjectPath”错误的可能方法(我专门使用ScriptLab),但我不认为我试图在多个上下文中使用任何方法 当前行为有时有效,但其他时候不会向单元格写入任何内容 var counter = 0; $("#run").click(run); async function run() { try { await Excel.run(
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
。这意味着在执行client.get
内部的回调之前,[在某些时候],将完成Excel.run
并“垃圾收集”(ish)一些对象(range
)
您可以通过多种方式解决此问题:
Excel.run
之前调用web服务。在这里的示例中(对于许多其他场景来说可能不现实,但在这里),在进行web调用之前,实际上根本不依赖文档中的任何内容。在这种情况下,根本不需要在Excel.run
中,您可以让Excel.run
成为web服务调用回调的一部分
var HttpClient=function(){
this.get=函数(aUrl){
返回新承诺(功能(解决、拒绝){
var anHttpRequest=newxmlhttprequest();
anhtprequest.onreadystatechange=函数(){
如果(anhtprequest.readyState==4&&anhtprequest.status==200){
解析(anhtprequest.responseText);
}否则{
拒绝(anhtprequest.statusText);
}
}
anhtprequest.open(“GET”,aUrl,true);
anHttpRequest.send(空);
});
}
}
同步时,获取选择是为数不多的几次之一,因为您希望捕获稍纵即逝的时间点选择,而不是web调用成功后X秒后的选择。因此,这是少数几种可能需要插入额外的wait context.sync()
的情况之一,即使您在技术上不需要它。有关更多信息,请参阅本书中的“5.8.2:何时同步”一节
=====
承诺API:
=====
来自关于承诺的:
=====
从实施细节部分:
问题在于,您没有等待完成客户端。获取。这意味着在执行client.get
内部的回调之前,[在某些时候],将完成Excel.run
并“垃圾收集”(ish)一些对象(range
)
您可以通过多种方式解决此问题:
在执行Excel.run
之前调用web服务。在这里的示例中(对于许多其他场景来说可能不现实,但在这里),在进行web调用之前,实际上根本不依赖文档中的任何内容。在这种情况下,根本不需要在Excel.run
中,您可以让Excel.run
成为web服务调用回调的一部分
将您的web服务调用包装在承诺中,以便等待它。类似这样:
var HttpClient=function(){
this.get=函数(aUrl){
返回新承诺(功能(解决、拒绝){
var anHttpRequest=newxmlhttprequest();
anhtprequest.onreadystatechange=函数(){
如果(anhtprequest.readyState==4&&anhtprequest.status==200){
解析(anhtprequest.responseText);
}否则{
拒绝(anhtprequest.statusText);
}
}
anhtprequest.open(“GET”,aUrl,true);
anHttpRequest.send(空);
});
}
}
我在一本关于使用Office.js构建Office插件的书中描述了这两种方法(以及更多…)。我在下面粘贴了一些相关书籍内容的截图
顺便说一句,我应该说,当您不想延迟同步时,获取选择是为数不多的几次之一,因为您希望捕获稍纵即逝的时间点选择,而不是web调用成功后X秒后的选择。因此,这是少数几种可能需要插入额外的wait context.sync()
的情况之一,即使您在技术上不需要它。有关更多信息,请参阅本书中的“5.8.2:何时同步”一节
=====
承诺API:
=====
来自关于承诺的:
=====
从实施细节部分:
请您将这些摘录作为引用文本而不是绘画提供,好吗?您不需要(也不应该)使用newpromise
构造函数来“允诺”jQuery ajax调用。只需执行返回承诺。解析($.ajax(…)。然后(…,…)
-jQuery已经返回了一个thenable(你甚至可以等待jQuery直接延迟)@Bergi,截图对我来说最简单,因为这本书是用LeanPub使用的方言Markdown(Markua
)编写的,但是GitHub并不总是100%的好。@Bergi,为了承诺jQueryAjax调用:jQuery确实会返回一个承诺,但不幸的是它不是一个承诺