2

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

是否有可能:

  • fetchAll每次请求完成时调用并构建和呈现卡片
  • 在初始渲染完成后触发一个函数(之后return card.build()
  • 更新根卡不返回(我试过CardService.newNavigation().popToRoot().updateCard(card.build())没有成功)

任何呈现卡片并在获取数据后对其进行更新的首选方式将不胜感激!

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

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);
  
4

1 回答 1

2

回答:

不幸的是,这是不可能的。

更多信息:

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

[是否可以]fetchAll每次请求完成时调用、构建和渲染卡片?

可以创建一个fetchAll函数来获取所有 API 响应,但您最终仍将等待 API 2 响应,然后再更新卡中可以看到的内容。

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

[是否可以]在初始渲染完成后触发函数(之后return card.build()

我对此进行了测试,而不是直接返回 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 作业,因此在 UI 中永远不会看到第二张卡返回。

[是否可以]更新根卡而不返回(我试过CardService.newNavigation().popToRoot().updateCard(card.build())没有成功)

updateCard()Navigation 类的一个方法。文档中有一个完整的页面详细介绍了卡片导航的使用,但这里要删除的重要部分是导航方法用于响应用户交互。从文档中:

如果用户交互或事件应导致在同一上下文中重新呈现卡片,请使用Navigation.pushCard()Navigation.popCard()Navigation.updateCard()方法替换现有卡片。

以下是导航示例:

  • 如果交互或事件改变了当前卡片的状态(例如,将任务添加到任务列表),请使用updateCard()
  • 如果交互或事件提供更多详细信息或提示用户进行进一步操作(例如,单击项目的标题以查看更多详细信息,或按下按钮以创建新的日历事件),请使用pushCard()显示新页面,同时允许用户使用后退按钮退出新页面。
  • 如果交互或事件更新了前一张卡片中的状态(例如,使用详细视图更新项目的标题),请使用类似popCard()popCard()pushCard(previous)pushCard(current)来更新前一张卡片卡和当前卡。

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

功能要求:

但是,您可以让 Google 知道这是一项很重要的功能,并且您希望他们实施该功能。Google 的问题跟踪器是开发人员报告问题并为其开发服务提出功能请求的地方。我建议为此使用G Suite 插件的功能请求模板,而不是直接使用 Apps 脚本。

参考:

于 2020-06-26T14:05:29.287 回答