【问题标题】:How to call google apps script server-side functions synchronously?如何同步调用谷歌应用脚​​本服务器端函数?
【发布时间】:2016-06-17 09:05:43
【问题描述】:

我写了一个谷歌应用脚​​本代码,它会打开一个谷歌电子表格,并按行列出值,但是有两个问题: 1. 随机顺序输出。 2. id为“loding”的div文本变为“Finished!”在列出所有值之前。 我认为当我通过“withSuccessHandler()”运行脚本时,脚本会等待服务器端函数返回,但事实并非如此。 我该如何纠正?

index.html:

<!DOCTYPE html>
<html>
    <head>
        <base target="_top">
        <script>
            function    jsListValue() {
                // Get count.
                google.script.run.withSuccessHandler(function(count) {
                    // List all values.
                    for( count; count>0; count=count-1) {
                        // Get a value.
                        google.script.run.withSuccessHandler(function(content) {
                            // Shows in "output".
                            var new_div = document.createElement("div");
                            new_div.appendChild(document.createTextNode(content));
                            document.getElementById("output").appendChild(new_div);
                        }).gsGetValue(count);
                    }
                    // Change loding notice.
                    document.getElementById("loding").innerHTML = "Finished!";
                }).gsGetCount();
            }
        </script>
    </head>
    <body onload="jsListValue()">
        <div id="output"></div>
        <div id="loding">Loding now...</div>
    </body>
</html>

代码.gs

function                doGet() {
    return HtmlService.createHtmlOutputFromFile('index').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function                gsOpenSheet() {
    // Return sheet of the note data.
    return (SpreadsheetApp.openById("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").getSheetByName("sheet1"));
}
function                gsGetCount() {
    // Return last row index in this sheet.
    return (gsOpenSheet().getLastRow());
}
function                gsGetValue(index) {
    // Return value in the (index,1).
    return (gsOpenSheet().getRange(index,1).getValue());
}

【问题讨论】:

  • 在这种情况下,您不应该获得单独的值。在这种情况下,您不需要获取单个值,因为 index 是行,并且行都是连续的。如果您需要获取不连续的行,那将是不同的。您正在对同一个服务器端函数进行多次快速调用。在这种情况下,无法保证服务器端函数返回值的顺序。同一函数的多个实例同时运行。它们不一定按顺序完成,因为服务器端功能可以同时运行。

标签: google-apps-script


【解决方案1】:

GAS 与 Javascript 非常相似,所有对 Google 的服务器端函数的调用都是异步的。你不能改变这个(至少我没有看到任何文档注册)。

您可以做的是,在客户端使用回调函数轮询服务器以获取“成功”返回值。它会继续轮询 1 分钟,否则退出。如果服务器返回成功值,则让它将客户端标志设置为“真”。除非标志为真,否则不应在客户端进行任何操作。通过这种方式,您可以控制客户端发生的事情。

【讨论】:

  • Apps 脚本有一个内置的方法来处理这个问题,请参阅下面的答案
  • @howMuchCheeseIsTooMuchCheese 好吧,这是记录在案的方法。但是服务器端函数仍然被异步调用,这与 OP 想要的不同。
【解决方案2】:

你想使用withSuccessHandlerDocs

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess(numUnread) {
        var div = document.getElementById('output');
        div.innerHTML = 'You have ' + numUnread
            + ' unread messages in your Gmail inbox.';
      }

      google.script.run.withSuccessHandler(onSuccess)
          .getUnreadEmails();
    </script>
  </head>
  <body>
    <div id="output"></div>
  </body>
</html>

【讨论】:

  • 对于那些仍然路过的人-请注意(只是为了减轻可能的误解)答案与withSuccessHandler的实际工作方式有关。在 Google Apps 脚本中没有同步方式使用客户端到服务器的通信。
【解决方案3】:

google.script.run 是异步的,这意味着无法预测gsGetValue(count) 将以什么顺序返回。当您使用withSuccessHandler 时,您必须在回调函数中执行下一个操作。

我的建议是获取您想要的所有范围并将其放在一个数组中。您可以创建一个服务器端函数来执行此操作。代码如下所示:

//Serverside function
function getDataForSearch() {
  const ws = SpreadsheetApp.openById("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").getSheetByName("sheet1");

  return ws.getRange(1,1,ws.getLastRow(),1).getValues();
}

getValues() 将返回一个数组数组,其中应包含指定范围内的所有值。更多关于here的信息

在您的客户端,脚本应该是这样的:


//array to get the data from getRange()
var data;

function jsListValue() {
   google.script.run.withSuccessHandler(function(dataReturned){
      data = dataReturned;
      var new_div;
      data.forEach(function(r){
         new_div = document.createElement("div");
         new_div.appendChild(document.createTextNode(r[0));
         document.getElementById("output").appendChild(new_div);
      });
      document.getElementById("loding").innerHTML = "Finished!";
   }).getDataForSearch();
}                        

【讨论】:

    【解决方案4】:

    正如@Iuri Pereira所暗示的,如果你从google脚本代码中返回一个参数,然后在页面javascript中使用它,那么程序会同步运行。

    HTML:

    <button onclick="google.script.run.withSuccessHandler(js_function).gs_code();">action</button>
    

    GS:

    function gs_code() {
       // do Something;
       return true;
    }
    

    HTML javascript:

    function js_function(gs_return_value) {
       console.log(gs_return_value);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-23
      • 2019-02-01
      • 1970-01-01
      • 2023-03-07
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多