我有一个使用 CardService 作为 UI 的 GMail 插件。卡片操作的某些回调函数需要超过 30 秒。因此,我收到以下错误。
Gmail 无法执行此附加操作。
有什么方法可以在服务器端异步运行 Google Apps 脚本功能,这样我就可以向用户返回一些通知并继续在幕后工作。
我尝试过使用一些像这样的库,但没有运气,我能够在语法上使用 Promises,但在功能上它仍然是同步的。
我有一个使用 CardService 作为 UI 的 GMail 插件。卡片操作的某些回调函数需要超过 30 秒。因此,我收到以下错误。
Gmail 无法执行此附加操作。
有什么方法可以在服务器端异步运行 Google Apps 脚本功能,这样我就可以向用户返回一些通知并继续在幕后工作。
我尝试过使用一些像这样的库,但没有运气,我能够在语法上使用 Promises,但在功能上它仍然是同步的。
截至目前,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 中查找长时间运行的响应数据。
如果您对此过程有任何疑问,请告诉我。
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==