在 Google Apps 脚本中获取数据后构建卡片并更新它

Building a card and updating it after fetching data in Google Apps Script

我正在尝试构建一个包含 2 个外部 API 调用的 Gmail 插件。第一个很快(~200ms),第二个很慢(~5s)。因此,我想先用第一次获取的结果构建卡片,然后在第二次调用完成后更新卡片。

是否可以:

任何呈现卡片然后在获取数据后更新它的首选方式将不胜感激!

下面是一个有用的示例函数。

function onGmailMessage(e) {
  // Fetching email
  var messageId = e.gmail.messageId;
  var accessToken = e.gmail.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);
  var message = GmailApp.getMessageById(messageId);

  // Preparing requests
  var data = {
    'text': message.getPlainBody(),
  };
  var options = {
    'method' : 'post',
    'contentType': 'application/json',
    'payload' : JSON.stringify(data)
  };

  // Fetching responses. Here I would love to first display
  // createCard(response_1) and then when the second call finishes
  // return createCard(response_1 + '/n' + response_2)
  var response_1 = UrlFetchApp.fetch('http://API_1/', options);
  var response_2 = UrlFetchApp.fetch('http://API_2/', options);
  return createCard(response_1 + '/n' + response_2);
  

答案:

很遗憾,这是不可能的。

更多信息:

这有点棘手,所以我将把这个答案分成三点:

[Is it possible to] call fetchAll and build and render the card each time a request finishes?

可以使用 fetchAll 函数来获取所有 API 响应,但您仍然需要等待 API 2 响应,然后才能更新卡.

问题是为了显示渲染的卡片,您需要制作某种 return。一旦您 return 第一个 API 的响应,您的第二个 API 将根本不会被执行,因为该函数已经执行。这导致第二点:

[Is it possible to] trigger a function after the initial rendering is done (after return card.build())

我用这个做了一个测试,而不是直接 returning API 1 的响应我将它的值存储在脚本 属性 中并在 200 毫秒后使用呼叫 API 2:

function onGmailMessage(e) {
 // previous code
  var response_1 = UrlFetchApp.fetch('http://API_1/', options);
  ScriptApp.newTrigger("getSecondResponse").timeBased().after(200).create();
  PropertiesService.getScriptProperties().setProperty('response1', response_1);  
  
  return createCard(response_1);  
}

function getSecondResponse() {
  // options 2 definition here;
  var response_1 = PropertiesService.getScriptProperties().getProperty("response1");
  var response_2 = UrlFetchApp.fetch('http://API_2/', options);
  return createCard(response_1 + '/n' + response_2);  
}

并在清单中添加正确的范围:

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/script.locale",
    "https://www.googleapis.com/auth/gmail.addons.current.action.compose",
    "https://www.googleapis.com/auth/gmail.addons.execute",
    "https://mail.google.com/",
    "https://www.googleapis.com/auth/script.scriptapp"
  ]
}

这确实调用了第一个API,在卡片中显示响应并且触发,卡片没有更新。我认为这是因为触发器作为一个 cron 作业从某个地方执行,而不是附加组件本身,所以第二张卡片 return 在 UI.[=27= 中从未出现过]

[Is it possible to] update the root card without returning it (I tried CardService.newNavigation().popToRoot().updateCard(card.build()) without success)

updateCard()Navigation class. There's a whole page in the documentation which details the uses of Card navigation 的一种方法,但这里要去掉的重要部分是导航方法用于响应 用户交互 .来自文档:

If a user interaction or event should result in re-rendering cards in the same context, use Navigation.pushCard(), Navigation.popCard(), and Navigation.updateCard() methods to replace the existing cards.

The following are navigation examples:

  • If an interaction or event changes the state of the current card (for example, adding a task to a task list), use updateCard().
  • If an interaction or event provides further detail or prompts the user for further action (for example, clicking an item's title to see more details, or pressing a button to create a new Calendar event), use pushCard() to show the new page while allowing the user to exit the new page using the back-button.
  • If an interaction or event updates state in a previous card (for example, updating an item's title from with the detail view), use something like popCard(), popCard(), pushCard(previous), and pushCard(current) to update previous card and the current card.

您可以创建多张具有不同内容的卡片 - 例如一张包含 response_1 和一张包含 response_1 + "\n" + response_2,但仍需要用户进行某种交互才能在两者之间切换两个视图,并且它不会绕过您需要从 API 获得响应的等待时间 2.

功能请求:

但是,您可以让 Google 知道这是一项重要的功能,并且您希望请求他们实现它。 Google 的 Issue Tracker is a place for developers to report issues and make feature requests for their development services. I would suggest using the feature request template for G Suite Add-ons 为此,而不是直接使用 Apps 脚本。

参考文献: