Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous execution of a function App Script

I've been digging around, and I'm not able to find references or documentation on how I can use Asynchronous Functions in Google App Script, I found that people mention It's possible, but not mention how...

Could someone point me in the right direction or provide me with an example? Promises, Callbacks, or something, that can help me with this.

I have this function lets call it foo that takes a while to execute (long enough that It could time out an HTTP call).

What I'm trying to do Is to refactor it, in a way that it works like this:

function doPost(e) {
    // parsing and getting values from e
    var returnable = foo(par1, par2, par3);
      return ContentService
             .createTextOutput(JSON.stringify(returnable))
             .setMimeType(ContentService.MimeType.JSON);
}

function foo(par1, par2, par3) {
    var returnable = something(par1, par2, par3); // get the value I need to return;

    // continue in an Async way, or schedule execution for something else
    // and allow the function to continue its flow
    /* async bar(); */

    return returnable;
}

Now I want to realize that bit in foo because It takes to long and I don't want to risk for a time out, also the logic that occurs there it's totally client Independent, so It doesn't matter, I just need the return value, that I'll be getting before.

Also, I think It's worth mentioning that this is deployed in Google Drive as a web app.

It's been long since this, but adding some context, at that moment I wanted to scheduled several things to happen on Google Drive, and It was timing out the execution, so I was looking for a way to safely schedule a job.

like image 326
ekiim Avatar asked Dec 18 '18 00:12

ekiim


People also ask

Is Google App script asynchronous?

google. script. run is an asynchronous client-side JavaScript API available in HTML-service pages that can call server-side Apps Script functions. To interact with dialogs or sidebars in Google Docs, Sheets, or Forms from client-side code, use google.

What is a function in Apps Script?

If you're familiar with Google Sheets, you've probably used functions such as SUM, AVERAGE, COUNT, etc. in formulas. Using Apps Script, you can also write your own functions. These are called custom functions. Once you create these functions, you can use them in Sheets just like any other function.

How do I stop a script from running on Google?

If you are in the code editor, and want to stop a script from running, you can click the "cancel" link in the toast display. Or you can click "View" -> "Executions" from the code editor and then terminate the script.


3 Answers

With the new V8 runtime, it is now possible to write async functions and use promises in your app script.

Even triggers can be declared async! For example (typescript):

async function onOpen(e: GoogleAppsScript.Events.SheetsOnOpen) {
    console.log("I am inside a promise");
    // do your await stuff here or make more async calls
}

To start using the new runtime, just follow this guide. In short, it all boils down to adding the following line to your appsscript.json file:

{
  ...
  "runtimeVersion": "V8"
}
like image 198
smac89 Avatar answered Oct 07 '22 18:10

smac89


  • You want to execute functions by the asynchronous processing using Google Apps Script.
  • You want to run the functions with the asynchronous processing using time trigger.

If my understanding is correct, unfortunately, there are no methods and the official document for directly achieving it. But as a workaround, that can be achieved by using both Google Apps Script API and the fetchAll method which can work by asynchronous processing.

The flow of this workaround is as follows.

  1. Deploy API executable, enable Google Apps Script API.
  2. Using fetchAll, request the endpoint of Google Apps Script API for running function.
    • When several functions are requested once, those work with the asynchronous processing by fetchAll.

Note:

  • I think that Web Apps can be also used instead of Google Apps Script API.
  • In order to simply use this workaround, I have created a GAS library. I think that you can also use it.
  • In this workaround, you can also run the functions with the asynchronous processing using time trigger.

References:

  • fetchAll
  • Deploy the script as an API executable
  • scripts.run of Google Apps Script API
  • Benchmark: fetchAll method in UrlFetch service for Google Apps Script
  • GAS library for running the asynchronous processing

If I misunderstand your question, I'm sorry.

like image 27
Tanaike Avatar answered Oct 07 '22 19:10

Tanaike


There is another way to accomplish this.

You can use time-based one-off triggers to run functions asynchronously, they take a bit of time to queue up (30-60 seconds) but it is ideal for slow-running tasks that you want to remove from the main execution of your script.

// Creates a trigger that will run a second later
ScriptApp.newTrigger("myFunction")
  .timeBased()
  .after(1)
  .create();

There is handy script that I put together called Async.gs that will help remove the boilerplate out of this technique. You can even use it to pass arguments via the CacheService.

Here is the link:

https://gist.github.com/sdesalas/2972f8647897d5481fd8e01f03122805

// Define async function
function runSlowTask(user_id, is_active) {
  console.log('runSlowTask()', { user_id: user_id, is_active: is_active });
  Utilities.sleep(5000);
  console.log('runSlowTask() - FINISHED!')
}

// Run function asynchronously
Async.call('runSlowTask');

// Run function asynchronously with one argument
Async.call('runSlowTask', 51291);

// Run function asynchronously with multiple argument
Async.call('runSlowTask', 51291, true);

// Run function asynchronously with an array of arguments
Async.apply('runSlowTask', [51291, true]);

// Run function in library asynchronously with one argument
Async.call('MyLibrary.runSlowTask', 51291);

// Run function in library asynchronously with an array of arguments
Async.apply('MyLibrary.runSlowTask', [51291, true]);
like image 22
Steven de Salas Avatar answered Oct 07 '22 20:10

Steven de Salas