Using the setInterval() method to refresh a UITable every 1 minute

Hi,

First off, thanks for this app. I really enjoy playing around with it. Executing IFTTT webhooks feels so much faster without having to listen to Siri saying “running your shortcut” first…

Now to the topic: I’ve never used JavaScript before and I’m currently trying to figure out how to refresh an UITable for the purpose of displaying the time since an event in my calendar has ended accurately.

For now I settled with using a dedicated refresh button but I was wondering if it could be automated with setInterval()?

I saw it being used in the “Countdown to midnight” example but trying it out myself I end up with a “ ReferenceError: Can’t find variable: setInterval”. Does this mean that setInterval() can only be used within an HTML context? Is there any other way I can reload an UITable every x min automatically?

Yes.

None that I’m aware of. I could be wrong though. Hopefully someone else can confirm.

There might be.

One way I can think of is to create a WebView and load a custom page in it, that makes every x minutes, or how often you like, a request to a specific url which you can freely choose. Then listen for that url with the WebView.onRequest property and if you get that url, update your UITable.

Sounds like this could work. Beautiful workaround.

This is also a great example of code I would extract into a module and reuse across my scripts using the new importModule(path) function.

Update

Come to think of it, I’m not sure this would work reliably. However, setting timers is a common problem in Scriptable so I’ve put it high on my todo list to add support for this.

Thanks for the input.

I guess I will stick to the refresh button for now and wait for future updates then.

If you are still interested in going the interval route, I have a module leveraging a WebView to return timed promises over here.

2 Likes

Oh yes! I had forgotten about your implementation :slight_smile: Very nice!

Hi,

Thanks for your input.

So I tried the example you provided in the other thread, but unfortunately it doesn’t quite work as expected. Maybe I’m doing it wrong?

I went ahead and simply copy-pasted both parts into a new file but basically what happens is that the first timer runs out correctly and logs the message at the correct time but the second one never seems to finish and keeps the script running forever.

Additionally, I found that if setting up 2 timers, but making the first one run longer then the second one leads to the first message being logged when the second (shorter running) timer runs out. The problem described above persists.

The second issue is expected: await waits for a Promise to return, that is the whole point of the keyword (the example uses it because Scriptable will not – or would not, as of 1.2 – wait for asynchronous operations to complete once the script has run). Using await to wait for the longer timer to return first thus means the second one will not be processed before that. Do not use await unless you absolutely need the return value right now, right there :innocent:.

This being said, the first issue (blocking) is unexpected and wasn’t present in my testing on Scriptable 1.2. I assume you are on 1.3 (or 1.3.1)? I will take a look when I have a moment.

That’s exactly right, I’m on 1.3.1. But I also realised that I actually don’t need multiple timers to make it work for my purposes.

let i=1
nextTimer(i)

async function nextTimer(){
 if (i<61){
   log("ITERATION: " + i)
   i++
   timer = null
   first = null
   timer = new Timer
   first = timer.add(1000)
   first.then(() => nextTimer(i)) 
   first
 } else {
 log("end")
 }
} 

The above might not make a good stopwatch but is sufficiently accurate for updating the UI every minute or so.