I need a DELAY method & setTimeout() is undefined (not found Window)
Hey,
I’m a newbie with JavaScript so this might be obvious …
I need a delay(ms) method to slow down the script after 5 API calls (limit 5/min.). Problem is all the JavaScript help on the intertube points to the setTimeout() method of the Window object. But it appears that Window is not instantiated inside the Airtable code block, therefore, no setTimeout() method. What’s a good workaround for this?
What might I be missing - other methods?
Thanks
David
Page 2 / 3
Other way around @Justin_Barrett; I’m using a 3rd party API with a restriction. Alpha Vantage - for stock market prices.
Do you know why the setTimeout() is not found?
How are you calling the other API? One of the APIs I use doesn’t allow you to pass your key through the URL and when I try to install https, it doesn’t seem to work.
In the script (JavaScript code):
let info = await fetch(https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${API_KEY});
But the format of the URL is API specific - this is for Alpha Ventures. You should read their docs/examples or call them.
In the script (JavaScript code):
let info = await fetch(https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${API_KEY});
But the format of the URL is API specific - this is for Alpha Ventures. You should read their docs/examples or call them.
Thanks for the info. This company doesn’t actually have API documentation which makes trying to find what to pass very frustrating. Their example shows “api-key” but it only works when using curl… I’ve reached out to their team and it seems like their knowledge of how it works is as good as their non-existent documentation.
Thanks for the info. This company doesn’t actually have API documentation which makes trying to find what to pass very frustrating. Their example shows “api-key” but it only works when using curl… I’ve reached out to their team and it seems like their knowledge of how it works is as good as their non-existent documentation.
Paste the CURL example here and I’ll bet we can transform the requirements into Airtable speak.
Paste the CURL example here and I’ll bet we can transform the requirements into Airtable speak.
let url = '"https://api-hazards.atcouncil.org/public/v1/wind.json?lat=llat variable]&lng=llong variable]';
let getOptions = {
method: "get",
headers: {
'api-key' : 'apiKeyHere',
'Accept' : 'application/json',
}
}
let postResults = await fetch(url, getOptions);
Something like:
let url = '"https://api-hazards.atcouncil.org/public/v1/wind.json?lat=[lat variable]&lng=[long variable]';
let getOptions = {
method: "get",
headers: {
'api-key' : 'apiKeyHere',
'Accept' : 'application/json',
}
}
let postResults = await fetch(url, getOptions);
That worked! Thank you, sir!
With how much our business uses random APIs like this, I plan on sharing this and another script we recently created in the forum once they’re up and running.
This strategy still doesn’t seem to work on my end. Here’s a complete example to demonstrate. Am I doing something wrong on my end?
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function test() {
output.text("foo");
await timeout(300);
output.text("bar");
}
test();
Expected: “foo” prints, then “bar” 300ms later.
Actual: “foo” prints, “bar” never does.
This strategy still doesn’t seem to work on my end. Here’s a complete example to demonstrate. Am I doing something wrong on my end?
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function test() {
output.text("foo");
await timeout(300);
output.text("bar");
}
test();
Expected: “foo” prints, then “bar” 300ms later.
Actual: “foo” prints, “bar” never does.
You need to await the test function when you call it.
await test();
This is the function I use:
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
I was just needing a DELAY and you’ve helped very much !
As I read the all thread coming from this one:
I would add that
window is globalThis here in the Script-Block.
Thank you and good night (GMT),
olπ
It is not working on my script. Do you guys have solution already for this?
It is not working on my script. Do you guys have solution already for this?
Welcome to the Airtable community!
It looks like you are using an automation script. The scripts which have been able to use setTimeout have been scripts run in Scripting app. There are a few differences between running a script as an automation and running a script in Scripting app. The ability to use setTimeout appears to be one of these differences.
Welcome to the Airtable community!
It looks like you are using an automation script. The scripts which have been able to use setTimeout have been scripts run in Scripting app. There are a few differences between running a script as an automation and running a script in Scripting app. The ability to use setTimeout appears to be one of these differences.
Do you know any alternative to put delay in automation script?
Do you know any alternative to put delay in automation script?
Why do you need a delay in your automation script? That might influence the approach. Two common approaches are reworking the trigger, or splitting the automation into two automations.
Why do you need a delay in your automation script? That might influence the approach. Two common approaches are reworking the trigger, or splitting the automation into two automations.
Well, I’m not sure if I can split it.
The trigger is when record is updated.
There’s no problem when the record being updated don’t have a dependent record.
When you update the name of the parent, the child get’s triggered as well because it has the parent’s name in a column (the update trigger). I wanted it in a way that the parent script operation gets executed first than the child. That’s why I wanted a delay for the child script.
Can you give more details on what you are trying to accomplish? What do you want your script to do? Are the parent and child records in the same table or different tables?
Do both the parent and child records trigger the same automation?
Remove window. should just be calling setTimeout() like in my code example
Thanks for clarifying the difference between automation and scripting block. This is a very helpful thread!
I just wanted to respond to a question you asked quite a while ago, as I didn’t see anyone else answering. I have at least one example of a situation in which you might need a delay in an automation…
In my case, I’m fetching from another API that has rate limits. If I exceed those rate limits, I get a status code OK=false, and the automation fails. This is not desirable. I’d like the automation to simply wait for a few seconds and try again so that I can honor the rate limits set by the external API.
You mentioned there may be other ways to achieve this without setTimeout(). Can you advise how you might approach the above scenario?
Thanks for clarifying the difference between automation and scripting block. This is a very helpful thread!
I just wanted to respond to a question you asked quite a while ago, as I didn’t see anyone else answering. I have at least one example of a situation in which you might need a delay in an automation…
In my case, I’m fetching from another API that has rate limits. If I exceed those rate limits, I get a status code OK=false, and the automation fails. This is not desirable. I’d like the automation to simply wait for a few seconds and try again so that I can honor the rate limits set by the external API.
You mentioned there may be other ways to achieve this without setTimeout(). Can you advise how you might approach the above scenario?
Thanks for any input!
The most common method of introducing a delay is to change the trigger of the automation to account for the delay.
Another option, is to call the Airtable api itself, awaiting the response. For example, you could create and delete a few records, one at a time. If you have a very large table, you could select the records in the table multiple times. The length of the delay is rather unpredictable, and may not be long enough for your needs. These calls are a complete waste of bandwidth, but without an official method of introducing a delay mid-script, we have to resort to whatever hacks we can.
However, I also suggest that you investigate why you might be exceeding the api’s rate limits. If you have multiple records triggering the same automation in the same narrow window of time, even introducing a delay in the script may not you solve your problem.
I just came up with a way to introduce a delay using date comparisons and a brute-force loop.
function delay(seconds) {
const startTime = (new Date()).getTime()
while ((new Date()).getTime() - startTime < seconds * 1000)
continue
}
Call that with the number of seconds that you want to wait, and it will return when it’s done.
I just came up with a way to introduce a delay using date comparisons and a brute-force loop.
function delay(seconds) {
const startTime = (new Date()).getTime()
while ((new Date()).getTime() - startTime < seconds * 1000)
continue
}
Call that with the number of seconds that you want to wait, and it will return when it’s done.
Always learning something new. Creating a new Date instance just to get its time is overkill when the same value is available via Date.now().
function delay(seconds) {
const startTime = Date.now()
while (Date.now() - startTime < seconds * 1000)
continue
}
So just to summarize and fix small errors in @Justin_Barrett answer. The following works for automation scripts perfectly without any error in editor. @Wylan_Osorio@Brian_Frank
/**
* @param {number} seconds
*/
function delay(seconds) {
const startTime = Date.now()
while (Date.now() - startTime < seconds * 1000)
continue
}
delay(10)
So just to summarize and fix small errors in @Justin_Barrett answer. The following works for automation scripts perfectly without any error in editor. @Wylan_Osorio@Brian_Frank
/**
* @param {number} seconds
*/
function delay(seconds) {
const startTime = Date.now()
while (Date.now() - startTime < seconds * 1000)
continue
}
delay(10)
Oops! Thanks for catching that typo. I didn’t copy the change from a working script, and just edited it here, and apparently got a little careless in my proofreading. I’ve updated my post to fix the error.
Always learning something new. Creating a new Date instance just to get its time is overkill when the same value is available via Date.now().
function delay(seconds) {
const startTime = Date.now()
while (Date.now() - startTime < seconds * 1000)
continue
}
Yeah, Unix time is pretty easy for any engine to grab. I think an even simpler busy loop might be a bit more precise in some edge cases, largely on account of how imprecise the Date API is when it comes to timing milliseconds.
Zealous punctuality probably isn’t a requirement for most Airtable use cases but I’ve been pretty happy with this for the past year:
Lifted the busy loop idea from StackOverflow and did a bit of testing with more reliable Python libraries last year - this method is usually under 2 ms off, or not at all. setTimeout is way less consistent, supposedly for security reasons. Oh, and while the Typescript linter doesn’t recognize it, setTimeout actually works inside the Scripting block. Obviously, it’s in the prototype chain of the globalConfig object but, also seems to have been inherited by the Scripting app wrapper. Not sure if Airtable failed to fully sanitize it together with the rest of window methods or if this is down to how inconsistent browsers still are when it comes to implementing some aspects of the interpreter.