I need a DELAY method & setTimeout() is undefined (not found Window)

Thanks guys!

Here it is:
curl --header “api-key: [apikeytxt]” -X GET "https://api-hazards.atcouncil.org/public/v1/wind.json?lat=[lat variable]&lng=[long variable]

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);
1 Like

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.

You need to await the test function when you call it.

await test();
2 Likes

Thank you very much @openside,
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π

1 Like

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.

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.

2 Likes

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?

doesnt work what else can i do?

Hi @kuovonne,

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 an api service that is specifically designed to mimic a slow api response. There used to be such a service at http://slowwly.robertomurray.co.uk/, but it is no longer functioning. There are instructions at GitHub - rob-murray/slowwly: A test service to mock a slow api response; responds to get and post methods for how to set up your own. Perhaps you can find another such service.

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.

5 Likes

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
}
2 Likes

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)
2 Likes

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.

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:

const timeout = (ms, start = Date.now(), i = 0, x) => {

while (!x) 

i < 1e7 

? i++ 

: x = Date.now() - start > ms

}

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.