【问题标题】:google.script.run is NOT running every time it is called. Some times the function runs, other times it does nothinggoogle.script.run 每次调用时都不会运行。有时函数运行,有时它什么也不做
【发布时间】:2018-10-02 07:00:07
【问题描述】:

在使用客户端 .HTML 文件时,在 Google 应用程序脚本中,您可以使用 google.script.run.(函数名称)调用服务器端脚本。

您可以在此处查看相关文档:https://developers.google.com/apps-script/guides/html/reference/run

现在,该脚本在其生命周期的前 6 个月左右一直在运行,没有出现任何问题。我没有接触过该程序,也没有收到通知或找到任何新弃用的代码。

然而,在过去几个月的过程中,我的用户一直报告说,当他们完成与 HTML 文档的交互时,关闭它时什么也没有发生,他们必须重复整个过程 3 次甚至有时甚至 4 次才能完成会得到它通过。, 这意味着当用户关闭客户端的 HTML 窗口时,应该调用服务器端的函数来处理剩余的任务,但在某些情况下不是这样。这个问题完全是随机的,似乎不是由任何特定原因引起的。

我自己已经采取了一些措施来尝试解决这个问题。我已将全部代码包装在 try catch 块中,包括 .HTML 和 .GS 文件。这意味着如果在 ANY 脚本中确实出现了 ANYTHING 错误,我会立即收到通知。然而,尽管如此,我还没有收到任何关于它失败的电子邮件,即使我亲眼看到它失败了。我在此功能之前和之后添加了日志命令,以查看它是停止一起工作还是继续工作。在每种情况下,无论函数调用是否成功,日志命令都会通过。

对我来说,这只能意味着函数 google.script.run 出于某种原因无法正常工作,并且无法运行相关函数,但没有返回错误消息或停止脚本。

我完全不知所措,因为我没有错误消息,没有可重复的步骤,并且之前没有这个问题的历史,而随着时间的推移突然开始变得越来越糟。我检查了谷歌的问题跟踪器没有结果。如果其他人正在使用此功能并且遇到问题,我希望您在这里分享您的经验。如果您有解决方案,请尽快让我知道。如果我不能解决这个问题,我将不得不完全使用一个新平台。

编辑 10/2: 在进一步研究这个问题后,我发现了这个项目所有执行的列表。我可以看到执行了哪些功能,执行时间和执行时间。我可以看到,当打开 HTML 服务的函数运行时,应该运行的下一个函数并不总是出现在列表中。如果没有,我可以看到用户重复他们的步骤,直到它运行。这支持了我的理论,即该函数在调用我的 script.run 后应该没有运行

【问题讨论】:

  • 有多少并发用户?最多允许同时执行 30 次。
  • 如果没有看到您的代码,很难确定问题所在。但是 google.script.run 不太可能“无法正常工作”,因为它被许多用户广泛使用。我的经验是在客户端尝试捕获 javascript 可能并不总是捕获错误。另一件事是异步客户端和服务器功能是如何运行的。您使用的是 withSuccessHandler 和 withFailureHandler 不是吗?
  • @Tehhowch 并发用户的数量永远不会超过 2 或 3。这个限制帐户是跨所有脚本还是仅在每个函数上?
  • MailApp.sendEmail() 在客户端代码中不起作用。您的onFailure 函数中有MailApp.sendEmail()。您需要从onFailure 向服务器发出google.script.run.functionName() 调用,然后从服务器发送电子邮件。
  • @Swordstoo,我注意到您的客户端脚本的另一件事是它在 processForm 之后立即调用 google.script.host.close。由于客户端服务器脚本是异步运行的,因此您的表单将在 processForm 返回之前关闭。所以你的成功处理程序实际上什么都不做。

标签: html google-apps-script web-applications


【解决方案1】:

Tl;dr:受影响的计算机运行缓慢,以至于 google.script.host.close 会在 google.script.run.functionName() 能够被调用并将信息从客户端传递到之前运行服务器,导致函数永远不会运行,但也不会返回错误。添加Utilities.sleep(1000) 解决了这个问题。

我在这里回答的情况是有人在未来偶然发现这个线程,因为他们遇到了类似的问题。 我能够通过在之间添加两行代码来解决这个问题 google.script.rungoogle.script.host.close。 我添加了 Google 的 Utilities.sleep(1000) 以强制计算机在执行函数和关闭 HTML 窗口之间等待一秒钟。我还添加了一个 HTML 警报,显示该函数已被调用并且没有遇到运行时错误。

我不知道为什么这似乎解决了这个问题,但我有一个理论。 我有大约 20 台计算机运行这个电子表格。他们中只有大约 6 人有这个问题,直到最近才引起我的注意。事实证明,出现问题的 6 台计算机是其中最慢的计算机。 我的理论是计算机太慢了,而且互联网带宽波动很大,以至于计算机根本没有时间调用 google.script.run 并从客户端 HTML 窗口传递信息,它只是被关闭了并在运行 google.script.host.close 时切断。这意味着该函数将不会存在于执行记录或历史记录中,也不会出现任何类型的运行时错误。在我的情况下,所有这些事情都是真实的。这也解释了为什么我在测试环境中的任何设备上都没有遇到过问题,因为它没有受到其他计算机出现任何减速的影响。

通过同时添加Utilities.sleep(1000) 和 UI 警报,这会强制 javascript 在用户与 UI 警报交互之前不会继续 google.script.host.close(这只是一个带有 OK 按钮的确认窗口),然后等待整整一秒钟。这牺牲了一点点用户友好性以获得更实用的脚本。由于我已经实施了这个“修复”,我的用户都没有报告任何问题,而且我所有的执行历史看起来都很好。

希望这对未来的路人有所帮助。

【讨论】:

    【解决方案2】:

    comments你贴出了这个函数sn-p:

    这是使用google.script.run 的脚本的基本副本:

    function onFailure(error) {
      MailApp.sendEmail("sparkycbass@gmail.com", "Order book eror", "ERROR: " + error.message);
      google.script.host.close();
    }
    function handleFormSubmit(formObject) { 
      google.script.run.withFailureHandler(onFailure).processForm(formObject)
      google.script.host.close();
    }
    

    这里的问题是 google.script.run is asynchronous - 对服务器端函数 processForm 的调用甚至不能保证在调用 google.script.host.close() 之前启动:

    客户端对服务器端函数的调用是异步的:在浏览器请求服务器运行函数doSomething() 之后,浏览器会立即继续下一行代码而不等待响应。这意味着服务器函数调用可能不会按照您期望的顺序执行。如果同时进行两个函数调用,则无法知道哪个函数会先运行;每次加载页面时结果可能会有所不同。在这种情况下,成功处理程序和失败处理程序有助于控制代码流。

    正确的模式是仅在服务器指示异步操作完成后调用“破坏性”命令 - 例如关闭主机并因此卸载所有相关的 Apps 脚本实例。这是在google.script.run 调用的成功处理程序中:

    .html

    function onFailure(error) { // server function threw an unhandled exception
      google.script.run.sendMeAnEmail("Order book error", "ERROR: " + error.message);
      console.log(error);
      document.getElementById("some element id").textContent = "There was an error processing that form. Perhaps try again?"
    }
    function onSuccess(serverFunctionOutput, userObj) {
      // do stuff with `serverFunctionOutput` and `userObj`
      // ...
      google.script.host.close();
    }
    function handleFormSubmit(formObject) {
      google.script.run
        .withFailureHandler(onFailure)
        .withSuccessHandler(onSuccess)
        .processForm(formObject);
    }
    

    .gs

    function processForm(formData) {
      console.log({message: "Processing form data", input: formData});
      // ...
    }
    function sendMeAnEmail(subject, message) {
      console.log({message: "There was a boo-boo", email: {message: message, subject: subject}});
      MailApp.sendEmail("some email", subject, message);
    }
    

    【讨论】:

    • 嘿@tehhowch 我尝试了两种处理程序的变体,但它们在我的代码中并不能始终如一地工作,我必须对处理程序进行更多研究才能实现它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 2019-01-14
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 2019-03-21
    相关资源
    最近更新 更多