Re: Setting timeout while awaiting for user input

2461 0
Showing results for 
Search instead for 
Did you mean: 
4 - Data Explorer
4 - Data Explorer

I am wondering if there is a way to set a timeout on an await call ?

Essentially I have a script where the user is asked a yes / no question, if the user says yes the script continues, if they say no the script aborts gracefully. Upon aborting two functions are run to update statuses in my tables.

However if the user does nothing, the script eventually timesout and aborts, and no “shutdown” functions are run.

My question is the following: can I limit the await user input call to x number of seconds, so that upon timeout I can run my functions before ending the script ?

Thanks in advance !



2 Replies 2

I’m not aware of an approach that would allow a script block to handle timeout events and creating a blocking (sleep mode) in a non-blocking script environment is ill-advised but this might work for you.

function timeout(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));

await timeout(1000); // 1 sec pause

Another approach:

  • When you enter the input await, set a flag in a table.
  • Clear the flag when the input is satisfied.
  • Create a script automation that runs every 15 minutes looking for records with the flag and perform the closing process, then clear the flag.

What you’re asking for is stretching the limits of what the Scripting app was meant to do.

Save for automations, another approach that comes to mind would be Promise-based, but it sounds like it’s time you graduate to writing custom apps, anyway.

Because even a command as simple as “wait for one or the other” isn’t as straightforward when dealing with JS’s single-threadedness. There’s one kind-of-native approach to dealing with it, though: the Promise.race method.

I just pulled this code from an older hobby project, cleaned it up as best as I could and confirmed it works in the scripting app:

class Frame {
    static menuBar = () => input.buttonsAsync('',['Option 1','Option 2'])

    // @ts-ignore
    static idle = (ms) => new Promise(resolve => setTimeout(resolve, ms || 2000, 'timeout'))

    render = async () => {
            buttons = Frame.menuBar(),
            interval = Frame.idle(),
            raceWinner = await Promise.race([buttons,interval])
        output.markdown(`# ${raceWinner}`)

await (new Frame).render()

I’ll probably open-source the whole thing eventually but the gist of it is that these 18 lines do exactly what you said, with the exception of the timeout duration - it’s set to two seconds here.

And yes, these are technically two frames, hence the reluctance to share this unfinished work haha.

The final line of the Frame.render method also illustrates how you can access the value of the async function once the race is done.

But again, it sounds like you might want to look into custom Airtable apps. Doing something like that in one of those is trivial because React pretty much does the state management for you, whereas here you’d just be using my own inferior take on React inside the sanitized Scripting app environment.

Also, this sentiment cannot be overstated enough but let me try, aynway:

creating a blocking (sleep mode) in a non-blocking script environment is ill-advised