2

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

Gmail 无法执行此附加操作。

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

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

4

2 回答 2

2

截至目前,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");
}

成功.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 中查找长时间运行的响应数据。

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

于 2018-03-28T13:50:36.980 回答
0

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

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

于 2020-12-05T14:23:20.450 回答