4

Hello mighty people of the internet :)

When playing around a bit with some JS I noticed that I was unable to use the return value of setInterval(function, milliseconds) inside clearInterval(var).

Here is a working version of clearing an interval:

const intervalId = setInterval(() => foo(), 500);
setTimeout(() => clearInterval(intervalId), 2000);

In this example an interval is calling the method foo() every 500ms. After 2s this will be stopped by the clearInterval(intervalId) nested in the setTimeout(function, milliseconds).

Not working is using setInterval inside clearInterval:

setTimeout(() => clearInterval(setInterval(() => foo(), 500)), 2000);
  • (Note: Replacing the arrow function syntax for a normal function call didn't change results)

Different to the example above, here no variable is used to hold the return value of setInterval().
Yet it results in the interval never being called / immediately stopped.
This appears very strange to me (and potentially could be a bug?).

May somebody can give an opinion / explain this?
Thank you :)

Community
  • 1
  • 1
Phy
  • 248
  • 1
  • 8
  • 3
    nothing will happen until the `setTimeout` fires, which means `setInterval` isn't called until then and `clearInterval()` is called immediately. – Mark Mar 15 '20 at 03:59
  • Oh yeah that is the big difference, totally didn't noticed that! – Phy Mar 15 '20 at 04:24

1 Answers1

3

Yes, you can set an interval or a timeout and then clear it with the ID of the timeout/interval - but, it doesn't make much sense, because then the interval function will never run, because the interval will be cleared immediately. That's what's happening here. If you don't want the interval to be cleared immediately, you should store the interval ID in a variable (like you're doing with int above).

Rather than storing the interval ID in a variable, you can also also pass the interval ID into an IIFE, but that's fundamentally doing the same sort of thing - the interval ID will be stored in the parameter rather than a standalone variable.

const foo = () => console.log('foo');

(int => {
  setTimeout(() => {
    clearInterval(int);
  }, 2000);
})(setInterval(foo, 500));

I'd also recommend:

  • If your timeout or interval is only going to call a function, just pass the function itself. No need to wrap it in another. Eg, as long as the calling context doesn't matter, you can always replace () => foo(); with foo();.
  • Using int for a variable name can be confusing to those who use other languages and expect int to be a keyword, not a variable name. Maybe call it intervalId instead?
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320