Curious to hear how others handle setInterval() in their custom widgets

Elizabeth_Fedak Member Posts: 106 MVP

Hey everyone, I'm really curious to hear about how you handle setInterval() in your custom widgets. I made a sliding image slider that automatically rotates and it's fine and dandy now, but I had an issue that was super specific to the editor. I didn't use any library because I had to calculate the aspect ratio on the images for each rotation to have a fixed height and contained view and didn't find the logic for the rotation or light box to be complicated, so I coded the entire thing. So to make sure my code was fine, I isolated the issue to a widget where I was only creating and clearing intervals that did nothing. After doing that, I realized a couple things that make it tricky to keep track of the IDs, even if you explicitly assign them to a variable and clear them at the right time. I wrote the solution that I came up with at the end to make the widget work as expected and handle having multiple instances on the same page etc.

While I was debugging it, I realized that a) the editor reruns the widget's outer function every time any little setting is changed in the Content Editor and, I think, creates a new closure, which means your interval IDs get lost and the variable that you used is assigned a brand new interval ID b) some toggles are set as 'undefined' instead of 'false' initially when you load a widget.

In my code, setInterval() is used if you select 3,4,5,6,7 or 8 second intervals for the images to automatically rotate the images every x seconds (or can be selected to be only on click). If you click back/forward, it clears the interval and resets it. Awesome. However, I noticed that if you were to go into the content editor and change it from say, 5 seconds to 6 seconds, that it would not clear the original timer using clearInterval() on the ID stored in the variable, and would just add a second timer, so it would rotate on cue with both a 5 and 6 second timer. Now imagine if you are adding images and trying different times and it starts rotating like crazy (and it's an infinite rotation). Not awesome. At first I thought I wasn't clearing the interval properly because of my code, but it wound up being because the variable was no longer referencing the value of the ID from the previous interval when the clearInterval() was called, because it was in a new execution context and nothing referenced that old variable anymore.

I tried many things before I decided to store the interval IDs on the window object. What I realized is that on a line like this:

let intervalID = setInterval(cb, time) ---- if I changed a setting in the Content Editor, Duda would reinvoke the outer function, so it would reassign a new interval ID to my variable intervalID. You need the ID of course to clear the interval, but it was now reassigned to the new ID of the interval, so I could of course only clear the present interval ID and not the old one.

I then tried to force clear any of the possible IDs w/ a simple for loop, but Duda uses setTimeout() on some calls and it was I think clearing those too so I had to rule that out as an option pretty quickly.

My solution:

So finally I created a unique property name with string concatenation and set it as a property on an intervalIDs object on the window so I could clear the appropriate interval IDs for each instance of my widget. (It's an image slider, so there might be more than 1 per page, so they couldn't share a property name.)

Anyway, I'm sure I'm not the only person trying to use setInterval() in the widget builder, so I'm wondering how everyone else makes it work correctly in the editor so that it doesn't leave stranded intervals running when changes are made in the Content Editor tab.

Also wasn't sure if that `undefined` thing on the toggle was a bug. I expected the values to only be true or false boolean types but when I was testing I realized that sometimes they are `undefined` until you interact w/ the toggle, which seems buggy.