# Window: setInterval() method



> **WARNING:**
> When the `code` parameter is used, this method dynamically executes its value as JavaScript.
> APIs like this are known as [injection sinks](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API#concepts_and_usage), and are potentially a vector for [cross-site-scripting (XSS)](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/XSS) attacks.
>
> You can mitigate this risk by always assigning [TrustedScript](https://developer.mozilla.org/en-US/docs/Web/API/TrustedScript) objects instead of strings and [enforcing trusted types](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types).
> See [Security considerations](#security_considerations) for more information.

The **`setInterval()`** method of the [Window](https://developer.mozilla.org/en-US/docs/Web/API/Window) interface repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.

## Syntax

```js-nolint
setInterval(code)
setInterval(code, delay)

setInterval(func)
setInterval(func, delay)
setInterval(func, delay, param1)
setInterval(func, delay, param1, param2)
setInterval(func, delay, param1, param2, /* …, */ paramN)
```

### Parameters

- `func`
  - : A [Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) to be executed every `delay` milliseconds.
    The first execution happens after `delay` milliseconds.
- `code`
  - : A [TrustedScript](https://developer.mozilla.org/en-US/docs/Web/API/TrustedScript) or a string of arbitrary code that is compiled and executed every `delay` milliseconds.
    This can be used instead of passing a function, but is _strongly discouraged_ for the same reasons that make using [eval()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Global_Objects%2Feval) a security risk.
- `delay` 
  - : The delay time between executions of the specified function or code, in milliseconds.
    Defaults to 0 if not specified.
    See [Delay restrictions](#delay_restrictions) below for details on the permitted range of `delay` values.
- `param1`, …, `paramN` 
  - : Additional arguments which are passed through to the function specified by _func_ once the timer expires.

### Return value

A positive integer (typically within the range of 1 to 2,147,483,647) that uniquely identifies the interval timer created by the call.

This identifier, often referred to as an "interval ID", can be passed to [clearInterval()](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval) to stop the repeated execution of the specified function.

### Exceptions

- [SyntaxError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError)
  - : The `code` can't be parsed as a script.
- [TypeError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError)
  - : Thrown if the `code` parameter is set to a string when [Trusted Types](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API) are [enforced by a CSP](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types) and no default policy is defined.
    It is also thrown if the first parameter is not one of the supported types: a function, string or `TrustedScript`.

## Description

The `setInterval()` function is commonly used to set a delay for functions that are executed again and again, such as animations.
You can cancel the interval using [clearInterval()](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval).

If you wish to have your function called _once_ after the specified delay, use [setTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout).

### Delay restrictions

It's possible for intervals to be nested; that is, the callback for `setInterval()` can in turn call `setInterval()` to start another interval running, even though the first one is still going.
To mitigate the potential impact this can have on performance, once intervals are nested beyond five levels deep, the browser will automatically enforce a 4 ms minimum value for the interval.
Attempts to specify a value less than 4 ms in deeply-nested calls to `setInterval()` will be pinned to 4 ms.

Browsers may enforce even more stringent minimum values for the interval under some circumstances, although these should not be common.
Note also that the actual amount of time that elapses between calls to the callback may be longer than the given `delay`; see [Reasons for delays longer than specified](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout#reasons_for_longer_delays_than_specified) for examples.

> **NOTE:**
> The `delay` argument is converted to a signed 32-bit integer, which limits the value to 2147483647 ms, or roughly 24.8 days.

### Interval IDs are shared with `setTimeout()`

The method returns an identifier that uniquely identifies the interval timer created by the call.
This identifier, which is often referred to as an "interval ID", can be passed to [clearInterval()](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval) to stop the repeated execution of the specified function.

Within the same global environment (e.g., a particular window or worker), the interval ID is ensured to remain unique and is not reused for any new interval timer as long as the original timer is still active.
However, different global environments maintain their own independent pools of interval IDs.

Be aware that `setInterval()` and [setTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout) share the same pool of IDs, and that `clearInterval()` and [clearTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout) can technically be used interchangeably.
For clarity, however, you should try to always match them to avoid confusion when maintaining your code.

### Ensure that execution duration is shorter than interval frequency

If there is a possibility that your logic could take longer to execute than the interval time, it is recommended that you recursively call a named function using [setTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout).
For example, if using `setInterval()` to poll a remote server every 5 seconds, network latency, an unresponsive server, and a host of other issues could prevent the request from completing in its allotted time.
As such, you may find yourself with queued up XHR requests that won't necessarily return in order.

In these cases, a recursive `setTimeout()` pattern is preferred:

```js
(function loop() {
  setTimeout(() => {
    // Your logic here

    loop();
  }, delay);
})();
```

In the above snippet, a named function `loop()` is declared and is immediately executed.
`loop()` is recursively called inside `setTimeout()` after the logic has completed executing.
While this pattern does not guarantee execution on a fixed interval, it does guarantee that the previous interval has completed before recursing.

### Functions are called with the global `this`

The functions passed to `setInterval()` is run with normal function call semantics for determining the reference of [`this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this).
This problem is explained in detail in the [JavaScript reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#callbacks).

For non-arrow functions, the `this` context is set to the [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) (an alias for [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window/window) in browsers) object.

The following example demonstrates how this can cause unexpected behavior. Here, when we pass the method `counter.count` directly to `setInterval()`, the `this` context is lost, and the method is called on the global object instead of the `Counter` instance, resulting in a `TypeError` when the `count` method tries to access `this`:

```js
class Counter {
  constructor() {
    this.data = new Map();
  }

  count(item) {
    this.data.set(item, (this.data.get(item) || 0) + 1);
  }
}

const counter = new Counter();

counter.count("foo"); // Successfully adds "foo" to the map
setInterval(counter.count, 1000, "bar");
// TypeError: Cannot read properties of undefined (reading 'set')
```

To work around this, you must make sure that the function passed to `setInterval` has the correct `this` context. There are three main ways to do this:

1. If you want to explicitly specify the `this` context, instead of passing the method directly, wrap the method call in another anonymous function that explicitly calls the method with the correct context:

   ```js
   setInterval(() => counter.count("bar"), 1000);
   setInterval(function () {
     counter.count("bar");
   }, 1000);
   ```

2. If you want to use the `this` context of the code that calls `setInterval()`, always use an arrow function, which inherits the `this` context of its enclosing scope:

   ```js example-bad
   class Counter {
     // …
     repeatedCount(item) {
       // BAD: the `this` context is lost in the callback
       setInterval(function () {
         this.data.set(item, (this.data.get(item) || 0) + 1);
       }, 1000);
     }
   }
   ```

   ```js example-good
   class Counter {
     // …
     repeatedCount(item) {
       // GOOD: the arrow function inherits the `this` context of `repeatedCount()`
       setInterval(() => {
         this.data.set(item, (this.data.get(item) || 0) + 1);
       }, 1000);
     }
   }
   ```

3. If you want to avoid extra function wrappers (which increase memory usage) while explicitly specifying the `this` context, you can use the [`Function.prototype.bind()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) method to create a new function with the correct `this` context:

   ```js
   setInterval(counter.count.bind(counter), 1000, "bar");
   ```

### Security considerations

The method can be used to execute arbitrary input passed in the `code` parameter.
If the input is a potentially unsafe string provided by a user, this is a possible vector for [Cross-site-scripting (XSS)](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/XSS) attacks.

For example, the following code shows how `setInterval()` might execute `untrustedCode` provided by a user:

```js example-bad
const untrustedCode = "alert('Potentially evil code!');";
const id = setInterval(untrustedCode, 1000);
```

Websites with a [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) that specifies [`script-src`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src) or [`default-src`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/default-src) will prevent such code running by default.
You can specify [`unsafe-eval`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#unsafe-eval) in your CSP to allow `setInterval()` to execute, but this is unsafe as it disables one of the main protections of CSP.

See [Inline JavaScript](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP#inline_javascript) in the CSP guide.

If you must allow the scripts to run via `setInterval()` you can mitigate these issues by always assigning [TrustedScript](https://developer.mozilla.org/en-US/docs/Web/API/TrustedScript) objects instead of strings, and [enforcing trusted types](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types) using the [`require-trusted-types-for`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/require-trusted-types-for) CSP directive.
This ensures that the input is passed through a transformation function.

To allow `setInterval()` to run, you will additionally need to specify the [`trusted-types-eval` keyword](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#trusted-types-eval) in your CSP `script-src` directive.
This acts in the same way as `unsafe-eval`, but _only_ allows the method to evaluate if trusted types are enabled (if you were to use `unsafe-eval` it would allow execution even on browsers that do not support trusted types).

For example, the required CSP for your site might look like this:

```http
Content-Security-Policy: require-trusted-types-for 'script'; script-src '<your_allowlist>' 'trusted-types-eval'
```

The behavior of the transformation function will depend on the specific use case that requires a user-provided script.
If possible you should lock the allowed scripts to exactly the code that you trust to run.
If that is not possible, you might allow or block the use of certain functions within the provided string.

## Examples

Note that these examples omit the use of trusted types for brevity.
See [Using `TrustedScript`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#using_trustedscript) in `eval()` for code showing the expected approach.

### Example 1: Basic syntax

The following example demonstrates `setInterval()`'s basic syntax.

```js
const intervalID = setInterval(myCallback, 500, "Parameter 1", "Parameter 2");

function myCallback(a, b) {
  // Your code here
  // Parameters are purely optional.
  console.log(a);
  console.log(b);
}
```

### Example 2: Alternating two colors

The following example calls the `flashtext()` function once a second until the Stop button is pressed.

#### HTML

```html
<div id="my_box">
  <h3>Hello World</h3>
</div>
<button id="start">Start</button>
<button id="stop">Stop</button>
```

#### CSS

```css
.go {
  color: green;
}
.stop {
  color: red;
}
```

#### JavaScript

```js
// variable to store our intervalID
let intervalId;

function changeColor() {
  // check if an interval has already been set up
  intervalId ??= setInterval(flashText, 1000);
}

function flashText() {
  const oElem = document.getElementById("my_box");
  oElem.className = oElem.className === "go" ? "stop" : "go";
}

function stopTextColor() {
  clearInterval(intervalId);
  // release our intervalId from the variable
  intervalId = null;
}

document.getElementById("start").addEventListener("click", changeColor);
document.getElementById("stop").addEventListener("click", stopTextColor);
```

#### Result

## Specifications

## Browser compatibility

## See also

- [Polyfill of `setInterval` which allows passing arguments to the callback in `core-js`](https://core-js.io/docs/features/web-standards/settimeout-setinterval)
- [Window.clearInterval()](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval)
- [WorkerGlobalScope.setInterval()](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/setInterval)
- [Window.setTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout)
- [Window.requestAnimationFrame()](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame)
