Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Excel中使用Office.js的竞赛条件_Javascript_Async Await_Office Js - Fatal编程技术网

Javascript 在Excel中使用Office.js的竞赛条件

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(

在下面的代码中,我遇到了某种竞争条件,我试图将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
。这意味着在执行
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

    =====

    来自关于承诺的

    =====

    从实施细节部分:


    问题在于,您没有等待完成
    客户端。获取
    。这意味着在执行
    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确实会返回一个承诺,但不幸的是它不是一个承诺