【问题标题】:Building a card and updating it after fetching data in Google Apps Script在 Google Apps 脚本中获取数据后构建卡片并对其进行更新
【发布时间】:2023-03-08 03:28:01
【问题描述】:

我正在尝试构建一个包含 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);
  

【问题讨论】:

    标签: google-apps-script gmail-addons


    【解决方案1】:

    答案:

    很遗憾,这是不可能的。

    更多信息:

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

    [是否可以] 调用 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 class 的一个方法。文档中有一个完整的页面详细说明了Card 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 的Issue Tracker 是开发人员报告问题并为其开发服务提出功能请求的地方。我建议为此使用 G Suite Add-ons 的功能请求模板,而不是直接使用 Apps 脚本。

    参考资料:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多