Last active
August 23, 2024 11:43
-
-
Save sdesalas/2972f8647897d5481fd8e01f03122805 to your computer and use it in GitHub Desktop.
Asynchronous execution for Google App Scripts (gas)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Async.gs | |
* | |
* Manages asyncronous execution via time-based triggers. | |
* | |
* Note that execution normally takes 30-60s due to scheduling of the trigger. | |
* | |
* @see https://developers.google.com/apps-script/reference/script/clock-trigger-builder.html | |
*/ | |
var Async = Async || {}; | |
var GLOBAL = this; | |
// Triggers asynchronous execution of a function (with arguments as extra parameters) | |
Async.call = function(handlerName) { | |
return Async.apply(handlerName, Array.prototype.slice.call(arguments, 1)); | |
}; | |
// Triggers asynchronous execution of a function (with arguments as an array) | |
Async.apply = function(handlerName, args) { | |
var trigger = ScriptApp | |
.newTrigger('Async_handler') | |
.timeBased() | |
.after(1) | |
.create(); | |
CacheService.getScriptCache().put(String(trigger.getUniqueId()), JSON.stringify({ handlerName: handlerName, args: args })); | |
return { | |
triggerUid: trigger.getUniqueId(), | |
source: String(trigger.getTriggerSource()), | |
eventType: String(trigger.getEventType()), | |
handlerName: handlerName, | |
args: args | |
}; | |
}; | |
// GENERIC HANDLING BELOW | |
// | |
function Async_handler(e) { | |
var triggerUid = e && e.triggerUid; | |
var cache = CacheService.getScriptCache().get(triggerUid); | |
if (cache) { | |
try { | |
var event = JSON.parse(cache); | |
var handlerName = event && event.handlerName; | |
var args = event && event.args; | |
if (handlerName) { | |
var context, fn = handlerName.split('.').reduce(function(parent, prop) { | |
context = parent; | |
return parent && parent[prop]; | |
}, GLOBAL); | |
if (!fn || !fn.apply) throw "Handler `" + handlerName + "` does not exist! Exiting.."; | |
// Execute with arguments | |
fn.apply(context, args || []); | |
} | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
// Delete the trigger, it only needs to be executed once | |
ScriptApp.getProjectTriggers().forEach(function(t) { | |
if (t.getUniqueId() === triggerUid) { | |
ScriptApp.deleteTrigger(t); | |
} | |
}); | |
}; |
@sdesalas Thank you so much for writing this! I've only just begun my journey as a developer and learned how to write asynchronous functions in Javascript today, only to find that it doesn't work in Google Apps Script. Your library worked like a charm for my purposes though. I managed to get the expected result on the first try, which is honestly incredibly surprising knowing me.
It seems so weird that you can write async function blah(), or return promises and write .then(), but Apps Script still runs it synchronously. Do you know why that is? What is the point of having the syntax if it doesn't work the way it was intended?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@ShadrinSpock see comment above
https://gist.github.com/sdesalas/2972f8647897d5481fd8e01f03122805?permalink_comment_id=4428924#gistcomment-4428924
In your case you probably want the ID of the folder. Instead of the folder object.