2

We have a small Google Apps Script webapp that handles Slack slash commands. It does some convenient things like adding, updating and querying records to our sheet, straight from Slack. Everything works just fine most of the time. However the Slack API expects an answer from the request in less than 3 seconds, or it will timeout. Our Google Apps Script is not always able to respond in that timeframe, which will only get worse as our sheet grows or our queries get more complicated.

The Slack API allows for the use of asynchronous calls using a delayed response, but that means that the Google Apps Script needs to respond immediately (within 3 seconds) and do some work in the background.

Now this is the problem

I can't figure out how to make an asynchronous call work in Google Apps Script

I know Workers are not supported in Google Apps Script and my solution below hits a wall because of ReferenceError: 'google' is not defined. (Just ignore the Payload class, it formats a Slack response)

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");
}

Does anyone have any idea how to make this work? Are there any alternative solutions to handle an asynchronous request in Google Apps Script?

TheMaster
  • 45,448
  • 6
  • 62
  • 85

1 Answers1

6

I'm not aware of any threading in Apps Script either and as you noticed google.script.run only works in the Apps Script frontend.

As a workaround you could use a Google Forms as your "task queue". I've put together a simple G-Form with one question and inspected its final version to get the appropriate parameter names and URL. Then I set an installable on-form-submit trigger to run my script. Here's my POC code:

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

It worked fine on my tests and should suffice for your use case.

Henrique G. Abreu
  • 17,406
  • 3
  • 56
  • 65