Rejoignez-nous

Sleep in JS : comment faire une pause en JavaScript

Dans cet article Dans cet article

Pour faire un sleep in JS, on utilise généralement une fonction basée sur Promise et setTimeout. JavaScript ne possède pas de fonction native sleep() qui bloque proprement l’exécution comme dans certains langages. La solution pratique consiste donc à créer une pause asynchrone, puis à l’utiliser avec await dans une fonction async.

const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function exemple() {
  console.log('Avant');
  await sleep(1000);
  console.log('Après 1 seconde');
}

exemple();

Cette approche est la plus lisible pour attendre un délai sans bloquer totalement le navigateur ou Node.js. Elle sert dans des cas concrets : espacer des appels API, simuler une latence, attendre avant une nouvelle tentative, ralentir une animation pilotée par JavaScript ou rendre un script de test plus proche d’un comportement réel.

Pour approfondir ce point, consultez La méthode Pomodoro.

Sleep in JS : la solution simple avec Promise et setTimeout

La fonction la plus courante tient en une ligne. Elle reçoit un nombre de millisecondes, crée une promesse, puis la résout après le délai demandé. Le moteur JavaScript peut continuer à gérer d’autres tâches pendant l’attente.

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Son utilisation repose sur await. Sans await, la promesse est créée, mais le code suivant continue immédiatement. C’est un point souvent source de confusion.

async function lancer() {
  console.log('Début');
  await sleep(2000);
  console.log('Deux secondes plus tard');
}

Le délai est exprimé en millisecondes. Une seconde correspond à 1000, deux secondes à 2000, une demi-seconde à 500. Le nom sleep n’a rien de spécial pour JavaScript : c’est simplement une fonction que vous créez. Vous pourriez l’appeler delay, wait ou pause. Beaucoup d’équipes préfèrent delay, car ce terme rappelle qu’il s’agit d’une attente asynchrone, pas d’un blocage total du programme.

La documentation MDN décrit setTimeout() comme une méthode qui lance une fonction après l’expiration d’un minuteur : https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout. C’est précisément ce mécanisme qui permet de construire un équivalent pratique de sleep en JavaScript.

Pourquoi JavaScript n’a pas de sleep bloquant classique

JavaScript a été conçu autour d’un modèle événementiel. Dans un navigateur, le même fil d’exécution peut gérer votre code, les interactions de l’utilisateur, certains traitements liés à l’interface et la file d’événements. Une fonction sleep() réellement bloquante poserait vite problème : la page pourrait sembler figée, les clics ne seraient plus traités, les animations s’arrêteraient et l’expérience deviendrait mauvaise.

C’est pour cette raison que la pause recommandée est presque toujours asynchrone. Au lieu de dire au moteur « arrête tout pendant deux secondes », on lui dit plutôt « reprends cette suite d’instructions dans deux secondes ». La nuance change tout dans la manière de raisonner.

Avec async et await, le code reste agréable à lire. On garde une forme linéaire, proche d’un script classique, tout en respectant le fonctionnement non bloquant de JavaScript.

async function afficherEtAttendre() {
  console.log('Chargement...');
  await sleep(1500);
  console.log('Suite du traitement');
}

Ce code ne bloque pas toute la page pendant l’attente. Il suspend seulement la suite logique de la fonction afficherEtAttendre. Le reste de l’application peut continuer à fonctionner.

Utiliser sleep dans une boucle sans bloquer l’application

Un cas fréquent consiste à ajouter une pause dans une boucle. Par exemple, vous voulez afficher des éléments un par un, envoyer des requêtes espacées ou rejouer une séquence étape par étape. Il faut alors utiliser une boucle compatible avec await, comme for...of ou une boucle for classique.

async function afficherMessages(messages) {
  for (const message of messages) {
    console.log(message);
    await sleep(1000);
  }
}

 afficherMessages(['Un', 'Deux', 'Trois']);

Chaque message apparaît avec une pause d’une seconde. Ce comportement est simple à comprendre, car l’exécution attend vraiment la promesse avant de passer au tour suivant.

Divers Conversion Mo Go : définition simple et usages concrets

Attention avec forEach. Cette méthode ne se combine pas naturellement avec await lorsque vous voulez exécuter les étapes l’une après l’autre. Le code suivant peut donner une impression trompeuse :

messages.forEach(async (message) => {
  await sleep(1000);
  console.log(message);
});

Ici, les attentes sont lancées de manière rapprochée. Les messages risquent de sortir presque en même temps après le délai, au lieu d’être espacés d’une seconde chacun. Pour un enchaînement séquentiel, préférez for...of.

Espacer des appels API avec une pause JavaScript

Le sleep en JavaScript est souvent utilisé pour contrôler le rythme des appels vers une API. Cela peut être utile lorsqu’un service impose une limite de requêtes, lorsqu’un script d’import doit rester progressif ou lorsqu’une interface doit éviter de déclencher trop d’actions d’un coup.

async function traiterUtilisateurs(utilisateurs) {
  for (const utilisateur of utilisateurs) {
    await envoyerVersApi(utilisateur);
    await sleep(500);
  }
}

Dans cet exemple, chaque utilisateur est envoyé, puis le script attend une demi-seconde avant de poursuivre. Cette approche est facile à relire et à ajuster. Si le délai doit évoluer, il suffit de modifier la valeur passée à sleep.

Pour une application de production, une pause fixe n’est pas toujours suffisante. Si une API répond avec une erreur temporaire, une stratégie de nouvelle tentative peut être plus adaptée. On peut alors combiner sleep avec une logique de retry.

async function appelerAvecRetry(action, tentatives = 3) {
  for (let essai = 1; essai <= tentatives; essai++) {
    try {
      return await action();
    } catch (erreur) {
      if (essai === tentatives) throw erreur;
      await sleep(1000 * essai);
    }
  }
}

Le délai augmente à chaque essai : une seconde, puis deux, puis davantage si vous adaptez le nombre de tentatives. Cette logique reste volontairement simple. Dans un système critique, il faut aussi gérer les codes de réponse, les journaux d’erreur, l’annulation et les limites propres au service appelé.

setTimeout seul ou sleep avec await : quelle différence ?

setTimeout peut être utilisé directement. C’est pratique pour déclencher une action plus tard, sans forcément attendre dans le flux principal du code.

console.log('Avant');

setTimeout(() => {
  console.log('Plus tard');
}, 1000);

console.log('Après');

Ce code affiche d’abord Avant, puis Après, puis Plus tard. La ligne placée après setTimeout n’attend pas. C’est normal : le minuteur programme une fonction pour plus tard et le script continue.

Avec sleep et await, vous écrivez plutôt :

async function demo() {
  console.log('Avant');
  await sleep(1000);
  console.log('Après');
}

Cette fois, dans la fonction demo, le message Après arrive bien après le délai. La différence principale n’est donc pas le minuteur utilisé, mais la façon d’organiser le flux d’exécution. setTimeout convient bien aux rappels simples. sleep avec await convient mieux quand plusieurs étapes doivent rester lisibles dans un ordre précis.

On peut résumer ainsi : si vous devez juste lancer une action plus tard, setTimeout suffit. Si vous devez suspendre une séquence asynchrone avant de continuer, une fonction sleep basée sur une promesse est plus confortable.

Les pièges à éviter avec sleep in JS

Le premier piège consiste à croire que le délai est garanti à la milliseconde exacte. En pratique, setTimeout programme une exécution après un minimum approximatif. Si le fil d’exécution est occupé, si l’onglet est en arrière-plan ou si l’environnement applique ses propres contraintes, le rappel peut arriver plus tard. Pour une animation fluide, il vaut souvent mieux utiliser requestAnimationFrame côté navigateur.

Le deuxième piège est d’utiliser sleep pour masquer un problème de synchronisation. Ajouter await sleep(1000) parce qu’une donnée « devrait être prête » dans une seconde peut rendre un bug plus discret sans le résoudre. Si votre code dépend d’une requête, attendez la promesse de cette requête. S’il dépend d’un événement, écoutez cet événement. Une pause arbitraire doit rester un choix assumé, pas une rustine permanente.

// Moins fiable
await sleep(1000);
utiliserDonnees();

// Plus clair
const donnees = await chargerDonnees();
utiliserDonnees(donnees);

Le troisième piège concerne les tests automatisés. Un sleep fixe rend souvent les tests plus lents et parfois instables. Dans Playwright, Cypress ou d’autres outils, il est généralement préférable d’attendre un sélecteur, une réponse réseau ou un état précis. La pause garde un intérêt pour simuler un délai, mais elle ne doit pas remplacer une attente fondée sur un signal réel.

Divers Livebox réinitialisation : la procédure à suivre selon votre modèle

Le quatrième piège est l’accumulation de délais invisibles. Une boucle de 100 éléments avec await sleep(500) prend déjà environ 50 secondes, sans compter le temps de traitement. Avant d’ajouter une pause dans une boucle, calculez son impact. Une attente agréable sur trois éléments peut devenir pénible sur un volume plus important.

Créer une fonction sleep plus pratique et réutilisable

Dans un projet, évitez de réécrire la fonction partout. Placez-la dans un fichier utilitaire, avec un nom clair. Vous pouvez aussi ajouter quelques garde-fous pour éviter les valeurs négatives ou les entrées inattendues.

export function sleep(ms) {
  const delay = Math.max(0, Number(ms) || 0);
  return new Promise(resolve => setTimeout(resolve, delay));
}

Cette version convertit la valeur en nombre et empêche un délai négatif. Elle reste simple, ce qui est souvent préférable. Une fonction utilitaire trop sophistiquée devient vite plus difficile à maintenir que le problème qu’elle résout.

Dans Node.js, vous pouvez aussi utiliser le module natif timers/promises dans les versions modernes. Il fournit une fonction déjà basée sur les promesses.

import { setTimeout as sleep } from 'node:timers/promises';

async function main() {
  await sleep(1000);
  console.log('Terminé');
}

main();

Cette option est pratique côté serveur, car elle évite de créer votre propre helper. Côté navigateur, la fonction maison avec Promise et setTimeout reste la solution habituelle.

Vous pouvez également prévoir une version annulable lorsque le contexte le demande, par exemple dans une interface où l’utilisateur peut fermer une fenêtre, changer d’écran ou interrompre une opération. L’annulation demande une logique plus avancée, souvent avec AbortController. Pour beaucoup de scripts simples, ce n’est pas nécessaire. Pour une application interactive, c’est une piste à envisager afin d’éviter qu’une action différée se déclenche après que l’utilisateur a quitté le contexte concerné.

Quand utiliser sleep en JavaScript et quand l’éviter

Utilisez sleep lorsque le délai fait partie du comportement attendu : patienter avant une nouvelle tentative, espacer volontairement des actions, rendre une démonstration plus lisible, simuler une latence ou cadencer une séquence. Dans ces situations, la pause a un sens métier ou technique clair.

Évitez sleep lorsque vous attendez une condition vérifiable. Une réponse API, un fichier chargé, un élément visible, une transaction terminée ou un événement utilisateur doivent être attendus directement. Le code gagne alors en fiabilité et en vitesse, car il reprend dès que la condition réelle est remplie.

La bonne question à se poser est simple : est-ce que j’ai besoin d’attendre un temps, ou est-ce que j’ai besoin d’attendre un état ? Si la réponse est un temps, sleep convient. Si la réponse est un état, cherchez la promesse, l’événement ou le mécanisme d’observation adapté.

Pour la majorité des besoins, cette version suffit :

const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

Elle est courte, compréhensible et compatible avec async/await. Le vrai enjeu n’est pas de trouver une fonction plus impressionnante, mais de l’utiliser au bon endroit. Un sleep bien placé rend un script plus clair. Un sleep ajouté par réflexe peut ralentir l’application, cacher une dépendance mal gérée ou rendre un test fragile.

En pratique, gardez cette règle : sleep sert à différer une suite d’instructions, pas à deviner quand le reste du monde sera prêt. Avec cette distinction, vous pouvez l’utiliser efficacement en JavaScript, aussi bien dans un navigateur que dans Node.js.

Donnez votre avis

Soyez le 1er à noter cet article
ou bien laissez un avis détaillé


Partagez cet article maintenant !


Réagissez à cet article

Partagez votre réaction