【问题标题】:Easiest way to wait for google server-side function to resolve等待谷歌服务器端功能解决的最简单方法
【发布时间】:2020-02-11 16:50:42
【问题描述】:

我需要客户端代码等待调用的服务器端 (google.script.run) 函数完成,然后再运行更多代码。

withSuccessHandler(successFunc) 不会导致服务器调用之后的代码行等待。

我做了什么:

async function func(){
   await google.script.run.withSuccessHandler(myFunc).serverFunc();
   console.log("done");
}
func();

代码如何等到服务器端函数解析后才执行console.log 行?

【问题讨论】:

  • 您的serverFunc() 是否返回承诺?您的代码应该等待它按原样解析
  • 您需要将您的“程序”(即serverFunc() 中的代码放在promise 中,并在“程序”完成时将resolve() 包装起来。让您的serverFunc 返回这个承诺,以便它可以等待。
  • @Nick Parsons 在google.script.run.withSuccessHandler(myFunc).serverFunc(),首先运行serverFunc()。这是 Google Apps 脚本,这是运行 Google 端的服务器。不幸的是,这并没有返回承诺。下一步,当serverFunc()没有出现错误时,运行withSuccessHandler并运行myFunc的函数。 Ref

标签: javascript google-apps-script web-applications promise async-await


【解决方案1】:

这个答案怎么样?请认为这只是几个答案之一。

模式一:

在这种模式下,serverFunc 运行后,myFunc 运行。当时console.log("done")myFunc中运行。

function myFunc() {
   console.log("done");
}

function func(){
   google.script.run.withSuccessHandler(myFunc).serverFunc();
}

func();

模式2:

在这个模式中,使用了 Promise。运行func()时,可以依次看到okdone

function myFunc() {
  return "ok";
}

async function func() {
  await new Promise(r => {
    google.script.run.withSuccessHandler(r).serverFunc();
  });
  const res = myFunc();
  console.log(res);
  console.log("done");
}

func();

注意:

  • 如果您测试以上示例,请在 Google Apps Script 端设置serverFunc() 的功能。
  • 这是一个简单的示例脚本。所以请根据您的实际情况进行修改。

参考资料:

如果这不是你想要的方向,我很抱歉。

补充:

如果您想在myFunc 处使用来自serverFunc 的值,下面的示例脚本怎么样?

示例脚本:

function myFunc(nice) {
  doStuffs(nice);

  return "ok";
}

async function func() {
  const e = await new Promise(r => {
    google.script.run.withSuccessHandler(r).serverFunc();
  });
  const res = myFunc(e);
  console.log(res);
  console.log("done");
}

func();
  • 在此脚本中,myFunc 的返回值可以通过res 检索。

【讨论】:

  • 在我的例子中,myFunc 有一个参数,它是 serverFunc() 的返回值,如下所示: function serverFunc(){ doSomething();返回“不错”; } 功能 myFunc(nice){ doStuffs(nice);我之前这样称呼它:google.script.run.withSuccessHandler(myFunc).serverFunc();在这种情况下, myFunc 是一个回调函数,如果我应用您的解决方案,则会出现错误,因为 ... () => r(myFunc())) .... (没有参数)感谢帮助:)
  • @Makoto Daiwa Ambara 感谢您的回复。我带来的不便表示歉意。从您的回复中,我可以知道您尝试使用模式 2。为此,我为您的回复添加了一个示例脚本。你能确认一下吗?如果这不是您想要的结果,我深表歉意。
  • 它可以正常工作,但如果我应用这个:console.log(res); otherFunc(); console.log(done); otherFunc() 不能正常工作,除非我使用 setTimeOut 这使得整个承诺设置无用。这是 otherFunc() 中的代码,可能可以提取一些为什么会发生这种情况的想法。
  • var btns = document.getElementsByTagName('button'); var mdls = document.getElementsByClassName("modal_detail"); var cds = document.getElementsByClassName("close_detail"); for(var i = 0;i<btns.length-1;i++){ btns[i].addEventListener("click",function(){ document.getElementById("mdl"+this.id.slice(3)).style.display = "block"; }); mdls[i].style.display = "none"; }
  • 请访问我的new issue
【解决方案2】:

此代码包括错误处理和两个Promise.then() 方法。 下面给出的示例是 Apps Script Web App 的完整代码,我将其用于测试目的,以确保该代码有效。 我需要一种方法来复制一些使用 fetch().then() 的客户端代码,将 fetch(url) 调用替换为使用 Apps 脚本 google.script.run.fncName()

H_Index

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <button onclick="some_Object_Name.innerNameOne()">Run</button>
    
    <div id="idRslt1">Result One</div>
    <div id="idRslt2">Result 2</div>
    <div id="idError">For error</div>
    
    <script>


function callServerAndGetRslt(po) {
  
  /*
    po.fncName - The name of the fnk to run
  
  */
  
  //console.log('po.fncName ' + po.fncName)
  
  return new Promise (function (resolve,reject) {
    google.script.run
      .withSuccessHandler (function (result) {
        console.log('result 24' + result)
        resolve (result);//What resolve does is return the result from the server back to the FIRST anonymous function in the "then" part
      })
      .withFailureHandler (function (error) {
        console.log('error: ' + error)
        reject (error);
      })[po.fncName](po);//There can NOT be anything inbetween the array and the ending parenthesis 
    })
}

function showError(err) {
  document.getElementById('idError').textContent = err;
  
}

function showResult(toShow) {
  document.getElementById('idRslt1').textContent = toShow;
  
}
function showResult2(toShow) {
  document.getElementById('idRslt2').textContent = toShow;
  
}

window.some_Object_Name = {

  innerNameOne : function() {
    return callServerAndGetRslt ({"fncName":'theFirstServerFncCall'})
      .then (function (result) {
        console.log('result: 45' + result)
        showResult (result);
      
        return callServerAndGetRslt ({"fncName":'serverFncCall2'});
      },//THERE MUST BE A COMMA HERE!!!!  This is a list of functions seperated by a comma
      function (error) {//Because this is the second function this is what gets called for an error
        showError(error);
        return "There was an error in call 1";
      }
      ).then (function (result) {
        showResult2("end result:" + result);
      });
  }
}

  </script>
  </body>
</html>

GS_Test

function theFirstServerFncCall(po) {
  Logger.log('po 1: ' + JSON.stringify(po))
  //throw new Error("err in first fnk");//This is for testing the 
  //error handling on the client side

  return ["name1","name2"];
}

function serverFncCall2(po) {
  Logger.log('po 2: ' + JSON.stringify(po))
  return [["one","two"]];
}

代码

function doGet() {
  return HtmlService.createHtmlOutputFromFile("H_Index");
}

【讨论】:

    【解决方案3】:

    谢谢!这也解决了我的下拉值服务器结果滞后的问题。这是我的代码:

    function createDropdowns() {
        
        loaddropdown("Dropdowns!A2:A","ctype");
        loaddropdown("Dropdowns!B2:B","state");
        loaddropdown("Dropdowns!C2:C","city");
        loaddropdown("Dropdowns!D2:D","remedies");
        loaddropdown("Dropdowns!E2:E","keywords");
    
        }
        async function loaddropdown(range,eid) {
        
        const e = await new Promise(r => {
        google.script.run.withSuccessHandler(r).getDropdownList(range);
        }); 
        filldropdown(e,eid);
    }
    
    //POPULATE HTML DROPDOWN
    
    function filldropdown(values, elemid) { 
        
        var list = document.getElementById(elemid);   
        for (var i = 0; i < values.length; i++) {
        var option = document.createElement("option");
        option.value = values[i];
        option.text = values[i];
        list.appendChild(option);
        
        }
    }
    

    【讨论】:

    • 感谢谁?你应该清楚地提到;)
    猜你喜欢
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 2016-04-13
    • 1970-01-01
    • 2014-11-29
    相关资源
    最近更新 更多