【问题标题】:Google Apps Script Async function execution on Server side在服务器端执行 Google Apps Script Async 函数
【发布时间】:2018-03-05 15:56:25
【问题描述】:

我有一个使用 CardService 作为 UI 的 GMail 插件。卡片操作的某些回调函数需要超过 30 秒。因此,我收到以下错误。

Gmail 无法执行此附加操作。

有什么方法可以在服务器端异步运行 Google Apps 脚本功能,这样我就可以向用户返回一些通知并继续在幕后工作。

我曾尝试使用像 one 这样的一些库,但没有运气,我能够在语法上使用 Promises,但在功能上它仍然是同步的。

【问题讨论】:

  • 没有看到您正在做什么的示例,我们所能提供的只是您应该通过使用CacheServicePropertiesService 来改进您的后端操作,以避免昂贵的计算。请注意,库和全局变量每次都会评估您的附加组件运行任何函数,因此通常不鼓励附加组件使用它们。
  • @Ruben 感谢您的评论。我想我最终需要重新设计我的后端计算。但是,我的问题的目的是确保无法在服务器端异步执行某些操作,也许最近从 GAS 端发生了一些变化或类似的事情。
  • 评论来自@tehhowch :)
  • @Rubén 抱歉 :) 对编辑感到困惑

标签: google-apps-script gmail-addons


【解决方案1】:

到目前为止,Gmail 插件没有异步执行。即使有东西,如果没有用户操作,也无法刷新 UI。

但是,有一个技巧。你可以做的是,如果有一个长时间运行的进程,只需创建一个“openlink”操作(设置链接),它应该打开一个带有 html 响应的 url (https://yourhtmlpageurl?redirect_uri=)。这个html可以有jquery ajax调用,可以等待一段时间。在 html 窗口中获得响应后,将页面重定向到通过传递响应数据传递的 redirect_uri。因此,我们的插件将获得一个回调函数,其参数为 json 对象,所有查询参数都指向 redirect_uri。获得预期响应后,使用CacheService 缓存响应。返回一些html成功模板,它应该会自动关闭窗口。

对于创建 openlink 操作:

用于生成带有状态令牌的重定向脚本 URI:

function generateNewStateToken(callbackName, user_info) {
return ScriptApp.newStateToken()
.withMethod(callbackName)
.withArgument("user_info", JSON.stringify(user_info))
.withTimeout(3600)
.createToken();
}

function getRedirectURI() {
    return "https://script.google.com/macros/d/" + ScriptApp.getScriptId() + "/usercallback";
}

var htmlUrl = <your_html_url> + "?redirect_uri="+ getRedirectURI() + "&state=" + generateNewStateToken("asyncCallback", {});

CardService.newOpenLink().setUrl(htmlUrl).setOpenAs(CardService.OpenAs.OVERLAY).setOnClose(CardService.OnClose.RELOAD_ADD_ON);

function asyncCallback(data) {
    data.response; // response which you can pass from script
    CacheService.getUserCache().put("long_running_process_resp", data.response);
    data.user_info; // user_info passed during state token creation
    // cache the data using cache service
    return HtmlService.createHtmlOutputFromFile("success");
}

success.html

<!DOCTYPE html>
<html>

  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
  </head>
  <body>
    <div class="sidebar">
        <p>Long running Process completed.</p>
    </div>
  </body>
  <script>
  setTimeout(function() {
    top.window.close();
  }, 2000);
  </script>
</html>

一旦success.html自行关闭,gmail插件就会刷新。因此,您可以从 CacheService 中查找长时间运行的响应数据。

如果您对此过程有任何疑问,请告诉我。

【讨论】:

    【解决方案2】:

    萨布的回答很好。但是,如果您想触发长时间运行的进程而不期望用户单击 openlink,您可以使用以下方式渲染图像: CardService.newImage().setImageUrl('https://yourservice.com/pixel/action.png?name=value&_nocache='+new Date().getTime())

    在服务器端,您可以将路径“/pixel/action.png”映射到长时间运行的代码,该代码在完成时会返回一个微小的透明像素 (1x1): 数据:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 2019-02-01
      • 2018-07-20
      • 2015-11-16
      • 1970-01-01
      • 2020-03-08
      相关资源
      最近更新 更多