Comment utiliser setInterval en JavaScript ? Exemples

Dans cet article

  • La méthode setInterval exécute une fonction de manière répétée à un intervalle défini en millisecondes
  • Il est indispensable d’appeler clearInterval pour stopper l’exécution et éviter les fuites mémoire
  • La différence principale avec setTimeout : setInterval répète l’appel, setTimeout ne l’exécute qu’une seule fois
  • L’intervalle minimum recommandé est de 10 ms ; en dessous, les navigateurs imposent un plancher de 4 ms
  • En production, je privilégie souvent un setTimeout récursif pour éviter l’empilement des appels sur les tâches longues
  • Depuis ES6, les arrow functions simplifient la syntaxe et règlent les problèmes de contexte this

En plus de dix ans de développement web, je peux affirmer que setInterval fait partie des fonctions JavaScript que l’on utilise dès ses premiers projets, mais que l’on maîtrise vraiment bien plus tard. Derrière sa simplicité apparente se cachent des subtilités qui peuvent provoquer des bugs difficiles à diagnostiquer : fuites mémoire, empilement d’appels, perte du contexte this. Dans ce guide, je vous montre comment utiliser setInterval en JavaScript correctement, avec des exemples concrets tirés de mes projets réels.

Comprendre setInterval en JavaScript

La méthode setInterval() est une fonction native de l’objet window (ou globalThis en Node.js) qui permet d’exécuter une fonction de manière répétée à intervalles réguliers. Concrètement, vous lui passez une fonction callback et un délai en millisecondes ; le navigateur appelle ensuite cette fonction encore et encore jusqu’à ce que vous l’arrêtiez explicitement.

Pour bien comprendre son fonctionnement, il faut savoir que JavaScript est mono-thread. L’exécution de setInterval repose sur la boucle d’événements (event loop) : le timer ne garantit pas une exécution à la milliseconde près, mais plutôt un délai minimum entre chaque appel. Si le thread principal est occupé, l’appel sera décalé. Ce mécanisme est détaillé dans la documentation MDN de setInterval.

Dans la pratique, j’utilise setInterval pour des tâches légères et régulières : mettre à jour un compteur, rafraîchir des données depuis une API, animer un carrousel. Pour des besoins plus sophistiqués comme un mécanisme de pause ou sleep en JavaScript, d’autres approches sont plus adaptées.

Éditeur de code affichant la syntaxe de setInterval avec coloration syntaxique
Éditeur de code affichant la syntaxe de setInterval avec coloration syntaxique

Syntaxe et paramètres de setInterval

La syntaxe de base est simple :

const intervalID = setInterval(fonction, delai, arg1, arg2, ...);

Voici le détail de chaque paramètre :

  • fonction : la fonction callback à exécuter à chaque intervalle
  • delai : le temps en millisecondes entre chaque exécution (1000 ms = 1 seconde)
  • arg1, arg2, … : des arguments optionnels passés à la fonction callback

La méthode retourne un identifiant numérique (intervalID) que vous devez conserver. C’est cet identifiant qui vous permettra d’arrêter l’intervalle plus tard avec clearInterval(). Si vous perdez cette référence, vous ne pourrez plus stopper l’exécution, ce qui constitue l’une des erreurs les plus fréquentes que je vois en revue de code.

// Syntaxe avec une arrow function (ES6+)
const timer = setInterval(() => {
  console.log('Exécution toutes les 2 secondes');
}, 2000);

// Syntaxe avec une fonction nommée
function afficherHeure() {
  console.log(new Date().toLocaleTimeString());
}
const timer2 = setInterval(afficherHeure, 1000);

// Syntaxe avec des arguments supplémentaires
function saluer(prenom, nom) {
  console.log(`Bonjour ${prenom} ${nom}`);
}
const timer3 = setInterval(saluer, 3000, 'Thomas', 'Renard');

Un point important : si vous omettez le paramètre delai, la plupart des navigateurs utilisent une valeur par défaut de 0 ms, mais en réalité le délai minimum imposé par les spécifications est de 4 ms pour les intervalles imbriqués au-delà du cinquième appel. En pratique, je recommande de ne jamais descendre en dessous de 10 ms pour garantir un comportement stable.

Exemples pratiques avec setInterval

Exemple 1 : un compteur simple

let compteur = 0;

const intervalCompteur = setInterval(() => {
  compteur++;
  document.getElementById('compteur').textContent = compteur;
  
  if (compteur >= 10) {
    clearInterval(intervalCompteur);
    console.log('Compteur terminé');
  }
}, 1000);

Ce pattern est celui que j’utilise le plus souvent : un compteur qui s’arrête automatiquement quand il atteint une condition. Notez comment clearInterval est appelé à l’intérieur même du callback.

Exemple 2 : horloge en temps réel

function demarrerHorloge() {
  const elementHorloge = document.getElementById('horloge');
  
  // Mise à jour immédiate puis toutes les secondes
  function mettreAJour() {
    const maintenant = new Date();
    elementHorloge.textContent = maintenant.toLocaleTimeString('fr-FR');
  }
  
  mettreAJour(); // Premier appel immédiat
  return setInterval(mettreAJour, 1000);
}

const horlogeID = demarrerHorloge();

Astuce que j’applique systématiquement : j’appelle la fonction une première fois immédiatement avant de lancer setInterval. Sans cela, l’utilisateur verrait un espace vide pendant la première seconde.

Exemple 3 : appel API périodique (polling)

const INTERVALLE_POLLING = 30000; // 30 secondes

const pollingID = setInterval(async () => {
  try {
    const response = await fetch('/api/notifications');
    const data = await response.json();
    
    if (data.length > 0) {
      afficherNotifications(data);
    }
  } catch (erreur) {
    console.error('Erreur de polling :', erreur);
  }
}, INTERVALLE_POLLING);

Ce type de polling est courant dans les applications web. Cependant, pour des projets en production, je privilégie aujourd’hui les WebSockets ou les Server-Sent Events qui sont plus efficaces.

Débogage d'un intervalle JavaScript dans la console du navigateur
Débogage d’un intervalle JavaScript dans la console du navigateur

clearInterval : arrêter l’exécution proprement

La fonction clearInterval() est le complément indispensable de setInterval. Elle prend en paramètre l’identifiant retourné par setInterval et stoppe définitivement l’exécution répétée.

// Démarrer un intervalle
const monInterval = setInterval(() => {
  console.log('En cours...');
}, 1000);

// L'arrêter après 5 secondes
setTimeout(() => {
  clearInterval(monInterval);
  console.log('Intervalle arrêté');
}, 5000);

Voici les règles que je m’impose dans tous mes projets :

  • Toujours stocker l’identifiant de l’intervalle dans une variable accessible
  • Toujours nettoyer les intervalles quand un composant est détruit (événement beforeunload, componentWillUnmount en React, onUnmounted en Vue)
  • Mettre à null la référence après l’appel à clearInterval pour éviter toute confusion
// Pattern de nettoyage complet
let refreshInterval = null;

function demarrerRefresh() {
  if (refreshInterval !== null) return; // Empêcher les doublons
  
  refreshInterval = setInterval(() => {
    actualiserDonnees();
  }, 5000);
}

function arreterRefresh() {
  if (refreshInterval !== null) {
    clearInterval(refreshInterval);
    refreshInterval = null;
  }
}

// Nettoyage automatique en quittant la page
window.addEventListener('beforeunload', arreterRefresh);

Ce pattern de garde contre les doublons est crucial. Sans la vérification if (refreshInterval !== null), chaque appel à demarrerRefresh() créerait un nouvel intervalle sans supprimer le précédent. J’ai vu ce bug provoquer des centaines d’appels API par minute sur un projet client.

Différence entre setInterval et setTimeout

C’est la question que l’on me pose le plus souvent en formation. Les deux fonctions gèrent des délais, mais leur comportement est fondamentalement différent :

Critère setInterval setTimeout
Nombre d’exécutions Répétée indéfiniment Une seule fois
Arrêt clearInterval() obligatoire clearTimeout() optionnel
Délai entre appels Fixe (peut s’empiler) Contrôlé si récursif
Risque d’empilement Oui, si le callback dure plus longtemps que l’intervalle Non (un seul appel)
Usage typique Polling, animations, horloges Délai unique, debounce
Précision temporelle Moyenne (dérive possible) Bonne (si récursif)

Pour résumer simplement : setTimeout exécute une fois après un délai, tandis que setInterval répète l’exécution à chaque intervalle. Si vous avez besoin d’exécuter quelque chose une seule fois avec un décalage, utilisez setTimeout. Si vous avez besoin d’une répétition régulière, setInterval est le choix naturel, bien que setTimeout récursif soit souvent préférable comme je l’explique plus loin.

Pour approfondir les mécanismes de temporisation en JavaScript, notamment les techniques de pause entre deux instructions, je vous recommande mon guide complet sur le sleep en JavaScript.

Pièges courants et bonnes pratiques

Piège n°1 : l’empilement des appels

C’est le problème le plus dangereux avec setInterval. Si votre callback met plus de temps à s’exécuter que l’intervalle défini, les appels s’empilent. Imaginez un appel API qui prend 3 secondes avec un intervalle de 2 secondes : les requêtes vont se chevaucher et potentiellement saturer votre serveur.

// MAUVAIS : risque d'empilement
setInterval(async () => {
  const data = await fetch('/api/donnees-lourdes'); // Peut prendre 3s+
  traiterDonnees(data);
}, 2000);

// BON : utiliser un flag pour éviter l'empilement
let enCours = false;

setInterval(async () => {
  if (enCours) return;
  enCours = true;
  
  try {
    const data = await fetch('/api/donnees-lourdes');
    traiterDonnees(data);
  } finally {
    enCours = false;
  }
}, 2000);

Piège n°2 : la perte du contexte this

Avant les arrow functions, la perte du contexte this était un cauchemar avec setInterval :

// PROBLÈME avec function classique
const monObjet = {
  compteur: 0,
  demarrer: function() {
    setInterval(function() {
      this.compteur++; // 'this' ne pointe PAS vers monObjet !
      console.log(this.compteur); // NaN
    }, 1000);
  }
};

// SOLUTION avec arrow function
const monObjet2 = {
  compteur: 0,
  demarrer: function() {
    setInterval(() => {
      this.compteur++; // 'this' pointe bien vers monObjet2
      console.log(this.compteur); // 1, 2, 3...
    }, 1000);
  }
};

Piège n°3 : oublier le nettoyage dans les SPA

Dans les applications single-page construites avec React, Vue ou Angular, les intervalles survivent à la destruction des composants si vous ne les nettoyez pas. C’est une source majeure de fuites mémoire.

// Exemple React avec useEffect
import { useEffect } from 'react';

function ComposantAvecTimer() {
  useEffect(() => {
    const intervalle = setInterval(() => {
      console.log('Tick');
    }, 1000);
    
    // Nettoyage au démontage du composant
    return () => clearInterval(intervalle);
  }, []);
  
  return <div>Mon composant</div>;
}

Piège n°4 : passer une chaîne au lieu d’une fonction

Comme eval(), setInterval accepte une chaîne de caractères en premier argument. C’est une faille de sécurité potentielle et une mauvaise pratique que je déconseille formellement :

// INTERDIT : vulnérable aux injections
setInterval('mettreAJour()', 1000);

// CORRECT : passer une référence de fonction
setInterval(mettreAJour, 1000);

La spécification HTML Living Standard du WHATWG détaille le fonctionnement interne des timers et les raisons pour lesquelles le passage de chaînes est déprécié.

Mise en place d'un compte à rebours dynamique avec setInterval en JavaScript
Mise en place d’un compte à rebours dynamique avec setInterval en JavaScript

setTimeout récursif : l’alternative recommandée

Après des années de pratique, je recommande souvent d’utiliser un setTimeout récursif plutôt que setInterval, surtout pour les tâches asynchrones. Voici pourquoi :

// setInterval : l'intervalle court pendant l'exécution du callback
// [--délai--][callback][--délai--][callback]
//                      ^ si le callback est lent, les appels s'empilent

// setTimeout récursif : le délai commence APRÈS la fin du callback
// [callback][--délai--][callback][--délai--]
//                                ^ aucun risque d'empilement

function pollingRecursif() {
  fetch('/api/statut')
    .then(response => response.json())
    .then(data => {
      afficherStatut(data);
      // Relancer le timer APRÈS le traitement
      setTimeout(pollingRecursif, 5000);
    })
    .catch(erreur => {
      console.error(erreur);
      // Relancer même en cas d'erreur (avec un délai plus long)
      setTimeout(pollingRecursif, 15000);
    });
}

// Premier appel
pollingRecursif();

Les avantages du setTimeout récursif sont nombreux :

  • Aucun risque d’empilement : le prochain appel ne démarre qu’une fois le précédent terminé
  • Contrôle du délai en cas d’erreur : vous pouvez augmenter le délai (backoff) en cas de problème réseau
  • Arrêt naturel : il suffit de ne pas rappeler setTimeout pour arrêter la boucle
  • Meilleure gestion async/await : compatible nativement avec les Promises

Cela dit, setInterval reste parfaitement adapté pour des tâches synchrones et légères comme animer un élément du DOM ou mettre à jour une horloge.

Cas d’usage concrets en production

Diaporama automatique

class Diaporama {
  constructor(selecteur, delai = 4000) {
    this.slides = document.querySelectorAll(`${selecteur} .slide`);
    this.indexActuel = 0;
    this.delai = delai;
    this.intervalID = null;
  }
  
  demarrer() {
    this.intervalID = setInterval(() => this.suivante(), this.delai);
  }
  
  arreter() {
    if (this.intervalID) {
      clearInterval(this.intervalID);
      this.intervalID = null;
    }
  }
  
  suivante() {
    this.slides[this.indexActuel].classList.remove('active');
    this.indexActuel = (this.indexActuel + 1) % this.slides.length;
    this.slides[this.indexActuel].classList.add('active');
  }
}

const slider = new Diaporama('#mon-slider', 3000);
slider.demarrer();

// Pause au survol
document.getElementById('mon-slider').addEventListener('mouseenter', () => slider.arreter());
document.getElementById('mon-slider').addEventListener('mouseleave', () => slider.demarrer());

Ce pattern est typique des projets de développement web sur-mesure où l’on construit des composants interactifs sans dépendre d’une bibliothèque externe.

Compte à rebours

function compteARebours(dateFinISO, elementID) {
  const element = document.getElementById(elementID);
  
  const intervalle = setInterval(() => {
    const maintenant = new Date().getTime();
    const fin = new Date(dateFinISO).getTime();
    const reste = fin - maintenant;
    
    if (reste <= 0) {
      clearInterval(intervalle);
      element.textContent = 'Terminé !';
      return;
    }
    
    const jours = Math.floor(reste / (1000 * 60 * 60 * 24));
    const heures = Math.floor((reste % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    const minutes = Math.floor((reste % (1000 * 60 * 60)) / (1000 * 60));
    const secondes = Math.floor((reste % (1000 * 60)) / 1000);
    
    element.textContent = `${jours}j ${heures}h ${minutes}m ${secondes}s`;
  }, 1000);
  
  return intervalle;
}

compteARebours('2026-12-31T23:59:59', 'countdown');

Sauvegarde automatique (auto-save)

let contenuPrecedent = '';

const autoSave = setInterval(() => {
  const contenuActuel = document.getElementById('editeur').value;
  
  if (contenuActuel !== contenuPrecedent) {
    fetch('/api/sauvegarder', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ contenu: contenuActuel })
    });
    contenuPrecedent = contenuActuel;
    afficherIndicateur('Sauvegardé');
  }
}, 10000); // Toutes les 10 secondes

Ce mécanisme d'auto-save est un classique que j'implémente régulièrement dans les CMS et constructeurs de sites. L'astuce consiste à comparer le contenu actuel avec le précédent pour éviter des requêtes inutiles.

Surveillance de la connexion

let estEnLigne = navigator.onLine;

setInterval(() => {
  if (navigator.onLine !== estEnLigne) {
    estEnLigne = navigator.onLine;
    
    const message = estEnLigne
      ? 'Connexion rétablie'
      : 'Connexion perdue, mode hors-ligne activé';
    
    afficherNotification(message);
  }
}, 3000);

Quand je développe des projets WordPress nécessitant un niveau d'expertise avancé, j'intègre souvent ce type de surveillance dans le back-office pour prévenir les pertes de données lors de la rédaction d'articles.

Notez que pour les événements liés au chargement de la page, comme onload, setInterval n'est pas le bon outil. Il vaut mieux utiliser window.addEventListener('load', callback) pour exécuter du code une fois le DOM entièrement chargé. setInterval est réservé aux tâches répétitives, pas aux événements ponctuels.

Concernant les équivalents dans d'autres langages, certains développeurs cherchent un setInterval en PHP. En PHP, le concept n'existe pas directement car le langage s'exécute côté serveur de manière synchrone. On utilise plutôt des tâches CRON pour planifier des exécutions répétées. J'en parle dans mon guide sur WP-CLI et la ligne de commande WordPress, où les tâches planifiées jouent un rôle central.

À retenir

  • Stockez toujours l'identifiant retourné par setInterval dans une variable pour pouvoir l'arrêter
  • Appelez clearInterval dans le cycle de destruction de vos composants (unmount, beforeunload) pour éviter les fuites mémoire
  • Préférez setTimeout récursif pour les appels asynchrones (API, fetch) afin d'éviter l'empilement
  • Utilisez les arrow functions pour conserver le contexte this dans vos callbacks
  • Ne passez jamais une chaîne en premier argument de setInterval ; utilisez une référence de fonction

Questions fréquentes


Comment utiliser setInterval en JavaScript ?

Pour utiliser setInterval, appelez setInterval(maFonction, delaiEnMs). Le premier argument est la fonction à exécuter de manière répétée, le second est l'intervalle en millisecondes. La méthode retourne un identifiant numérique que vous devez conserver pour pouvoir stopper l'exécution avec clearInterval(identifiant). Par exemple, const id = setInterval(() => console.log('tick'), 1000) affichera « tick » toutes les secondes.


Qu'est-ce que la fonction interval en JavaScript ?

La fonction interval, ou plus précisément setInterval(), est une méthode native de l'API Web qui crée un timer répétitif. Elle appartient à l'objet window dans les navigateurs et à globalThis dans Node.js. Son rôle est d'exécuter une fonction callback à intervalles réguliers définis en millisecondes, jusqu'à ce qu'elle soit explicitement arrêtée par clearInterval() ou que la page soit fermée.


Comment puis-je créer un intervalle en JS ?

Pour créer un intervalle en JavaScript, utilisez la syntaxe suivante : const monTimer = setInterval(fonctionCallback, 2000). Cela exécutera la fonction toutes les 2 secondes (2000 ms). Vous pouvez passer des arguments supplémentaires après le délai : setInterval(maFonction, 1000, arg1, arg2). Pour arrêter l'intervalle, appelez clearInterval(monTimer). En environnement React ou Vue, pensez à nettoyer l'intervalle lors du démontage du composant.


La différence entre == et === en JS ?

L'opérateur == (égalité faible) compare deux valeurs en effectuant une conversion de type automatique : "5" == 5 retourne true. L'opérateur === (égalité stricte) compare à la fois la valeur et le type : "5" === 5 retourne false. En pratique, il est recommandé d'utiliser systématiquement === pour éviter les comportements imprévisibles liés à la coercition de types. C'est d'ailleurs une règle imposée par la plupart des linters comme ESLint.


Comment arrêter un setInterval en JavaScript ?

Pour arrêter un setInterval, utilisez la fonction clearInterval() en lui passant l'identifiant retourné par setInterval. Exemple : const id = setInterval(maFonction, 1000); clearInterval(id);. Pensez à stocker l'identifiant dans une variable accessible depuis l'endroit où vous souhaitez stopper l'intervalle. Après l'appel à clearInterval, mettez la variable à null pour éviter toute confusion.


setInterval fonctionne-t-il en arrière-plan dans le navigateur ?

Les navigateurs modernes ralentissent ou suspendent les timers (setInterval et setTimeout) dans les onglets inactifs pour économiser les ressources. Chrome, par exemple, limite les intervalles à un minimum d'une seconde dans les onglets en arrière-plan, et peut même les suspendre complètement après 5 minutes d'inactivité. Pour les tâches critiques en arrière-plan, envisagez l'utilisation de Web Workers ou de l'API Page Visibility pour adapter le comportement de votre application.


Damien Roux
Damien Roux

Ingénieur système et expert hébergement web. Fondateur de web-city.fr, il partage guides pratiques, comparatifs objectifs et outils gratuits pour choisir le bon hébergeur et créer son site WordPress.

Retour en haut