首页 > 解决方案 > 如何使用 Google Apps Script webapp 发送延迟响应(Slack api)?

问题描述

我们有一个处理 Slack 斜杠命令的小型 Google Apps Script webapp。它做一些方便的事情,比如直接从 Slack 向我们的工作表添加、更新和查询记录。大多数时候一切都很好。然而,Slack API 期望请求在 3 秒内得到答复,否则它将超时。我们的 Google Apps 脚本并不总是能够在该时间范围内做出响应,随着工作表的增长或查询变得更加复杂,这种情况只会变得更糟。

Slack API 允许使用延迟响应的异步调用,但这意味着 Google Apps 脚本需要立即响应(在 3 秒内)并在后台执行一些工作。

现在这是问题

我不知道如何在 Google Apps 脚本中进行异步调用

我知道 Google Apps 脚本不支持 Worker,下面的解决方案因为ReferenceError: 'google' is not defined而碰壁。(只需忽略 Payload 类,它会格式化 Slack 响应)

function doPost(request) {
  var responseUrl = request.parameter.response_url

  // This is how I try to circumvent the lack of threads in Google Apps Script
  google.script.run

  // Send an asynchronous slack response with result
  .withSuccessHandler(function(payload) {
    UrlFetchApp.fetch(responseUrl, {
      'method' : 'post',
      'contentType': 'application/json',
      'payload' : payload.toString()
    });
  })

  // Send an asynchronous slack response with error message
  .withFailureHandler(function(payload) {
    UrlFetchApp.fetch(responseUrl, {
      'method' : 'post',
      'contentType': 'application/json',
      'payload' : payload.toString()
    });
  })

  // do work in the background
  .sleep(5);
  
  return new Payload("Let me think about this...").asResponse();
}

function sleep(seconds) {
  Utilities.sleep(1000 * seconds);
  return new Payload("I waited for " + seconds + " seconds");
}

有谁知道如何使这项工作?是否有任何替代解决方案来处理 Google Apps 脚本中的异步请求?

标签: asynchronousgoogle-apps-scriptslack-api

解决方案


我也不知道 Apps Script 中的任何线程,正如您所注意到的,它google.script.run仅适用于 Apps Script 前端。

作为一种解决方法,您可以使用 Google 表单作为您的“任务队列”。我已经将一个简单的 G-Form 与一个问题放在一起,并检查了它的最终版本以获取适当的参数名称和 URL。然后我设置了一个可安装的表单提交触发器来运行我的脚本。这是我的 POC 代码:

function doPost(e) {
  var form = 'https://docs.google.com/forms/d/e/1FAIpQLScWBM<my-form-id>CRxA/formResponse';
  UrlFetchApp.fetch(form, {method:'POST', payload:'entry.505669405=' + e.parameter.example});
  return ContentService.createTextOutput('OK');
}

function onForm(e) {
  //triggered async from doPost via a Google Forms
  SpreadsheetApp.getActive().getSheetByName('Sheet1').appendRow(e.values);
}

它在我的测试中运行良好,应该足以满足您的用例。


推荐阅读