
Dans cet article
- JavaScript ne possède aucune fonction sleep() native, contrairement à PHP ou Python
- La combinaison Promise + setTimeout est la méthode recommandée pour créer un sleep fiable
- Les mots-clés async/await permettent d’écrire un sleep lisible en seulement 3 lignes de code
- Un sleep synchrone bloque le thread principal et gèle l’interface utilisateur : à éviter absolument
- La fonction setTimeout seule ne met pas en pause l’exécution, elle planifie un callback
- Des alternatives comme requestAnimationFrame ou les Web Workers existent pour des cas spécifiques
Sommaire
- Pourquoi JavaScript n’a pas de fonction sleep native
- Créer une fonction sleep avec Promise et setTimeout
- Utiliser async/await pour un sleep propre
- setTimeout vs sleep : comprendre la différence
- Sleep synchrone en JavaScript : pourquoi l’éviter
- Cas pratiques et exemples avancés
- Comparatif des méthodes de temporisation
- Erreurs courantes et bonnes pratiques
En tant que développeur web depuis 2014, je me souviens encore de ma frustration la première fois que j’ai cherché une fonction sleep en JavaScript. Venant du monde PHP avec son simple sleep(5), je m’attendais à trouver un équivalent direct. La réalité est tout autre : JavaScript fonctionne sur un modèle asynchrone qui rend cette opération fondamentalement différente. Après des années à construire des applications web, je vous partage dans ce guide toutes les méthodes pour implémenter un javascript sleep fiable, avec des exemples concrets tirés de mes projets.
Pourquoi JavaScript n’a pas de fonction sleep native
Pour comprendre l’absence de sleep natif, il faut saisir le fonctionnement fondamental de JavaScript. Le langage repose sur un modèle mono-thread et non-bloquant, piloté par une boucle d’événements (event loop). Contrairement à des langages comme PHP, Python ou Java, JavaScript n’a qu’un seul thread d’exécution principal dans le navigateur.
Si une fonction sleep bloquante existait nativement, elle figerait tout le navigateur pendant la durée d’attente : pas de scroll, pas de clic, pas d’animation. L’expérience utilisateur serait catastrophique. C’est précisément pour cette raison que les créateurs du langage ont opté pour un modèle asynchrone dès le départ.
La boucle d’événements fonctionne de manière élégante. Quand vous demandez une temporisation avec setTimeout, JavaScript enregistre le callback, continue d’exécuter le reste du code, puis revient au callback une fois le délai écoulé. Ce mécanisme est au cœur de tout ce qui touche à la pause javascript et aux temporisations.

Selon la documentation MDN sur la boucle d’événements, chaque message dans la file d’attente est traité complètement avant que le suivant ne soit pris en charge. Ce comportement explique pourquoi un sleep synchrone bloque littéralement tout le processus.
Cette architecture asynchrone est devenue un avantage compétitif de JavaScript, notamment avec Node.js qui gère des milliers de connexions simultanées grâce à ce modèle. Mais pour nous développeurs, cela signifie qu’il faut adopter une approche différente pour mettre en pause l’exécution du code.
Créer une fonction sleep avec Promise et setTimeout
La méthode la plus répandue et recommandée pour créer un javascript sleep combine les Promises et setTimeout. Voici la fonction que j’utilise dans tous mes projets :
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Cette fonction tient en une seule ligne et fait exactement ce qu’on attend d’elle. Elle crée une Promise qui se résout automatiquement après le nombre de millisecondes spécifié. Le mécanisme est simple : setTimeout appelle la fonction resolve de la Promise après le délai, ce qui signale que l’attente est terminée.
Pour l’utiliser avec la syntaxe .then(), voici un exemple concret :
console.log('Début du traitement');
sleep(2000).then(() => {
console.log('Affiché après 2 secondes');
});
console.log('Ce message apparaît immédiatement');
Le résultat dans la console sera :
- « Début du traitement » (immédiat)
- « Ce message apparaît immédiatement » (immédiat)
- « Affiché après 2 secondes » (après 2s)
Remarquez que le troisième console.log s’exécute avant le callback du sleep. C’est le comportement asynchrone de JavaScript en action. Le code ne se met pas en pause : il continue à s’exécuter et revient au callback plus tard. Si vous avez besoin de manipuler des structures de données comme les Set en JavaScript, cette même logique asynchrone s’applique lorsque vous combinez itérations et temporisations.
Pour enchaîner plusieurs sleep, on peut utiliser le chaînage de Promises :
sleep(1000)
.then(() => {
console.log('1 seconde écoulée');
return sleep(2000);
})
.then(() => {
console.log('3 secondes au total');
return sleep(1000);
})
.then(() => {
console.log('4 secondes au total');
});
Cette approche fonctionne, mais on voit rapidement que le code devient verbeux. C’est là qu’async/await entre en jeu.
Utiliser async/await pour un sleep propre
La syntaxe javascript sleep await est de loin la plus élégante. Introduite avec ES2017, elle permet d’écrire du code asynchrone qui se lit comme du code synchrone. Avec la même fonction sleep définie plus haut, voici comment l’utiliser :
async function processSequentiel() {
console.log('Étape 1 : initialisation');
await sleep(1000);
console.log('Étape 2 : chargement des données');
await sleep(2000);
console.log('Étape 3 : traitement terminé');
}
processSequentiel();
Cette fois, les messages s’affichent dans l’ordre, avec les délais attendus. Le mot-clé await met réellement en pause l’exécution de la fonction async, sans pour autant bloquer le thread principal. Le navigateur reste réactif pendant toute la durée de l’attente.
Voici un exemple plus réaliste que j’utilise régulièrement, un système de retry avec délai croissant pour les appels API :
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
async function fetchAvecRetry(url, maxRetries = 3) {
for (let tentative = 0; tentative < maxRetries; tentative++) {
try {
const response = await fetch(url);
if (response.ok) return await response.json();
throw new Error(`HTTP ${response.status}`);
} catch (erreur) {
console.warn(`Tentative ${tentative + 1} échouée : ${erreur.message}`);
if (tentative < maxRetries - 1) {
const delai = 1000 * Math.pow(2, tentative);
console.log(`Nouvelle tentative dans ${delai}ms...`);
await sleep(delai);
}
}
}
throw new Error('Toutes les tentatives ont échoué');
}
Ce pattern d'exponential backoff est fondamental en développement web. Le délai double à chaque tentative (1s, 2s, 4s), ce qui évite de surcharger un serveur déjà en difficulté. Je l'utilise systématiquement dans mes projets professionnels.

Un point important : await ne peut être utilisé qu'à l'intérieur d'une fonction déclarée async, ou au niveau racine d'un module ES (top-level await). Si vous obtenez l'erreur "await is only valid in async functions", vérifiez que votre fonction englobante porte bien le mot-clé async.
Pour un javascript sleep 1 second, l'écriture la plus directe est :
await sleep(1000); // pause d'une seconde
Et pour un javascript sleep 5 seconds :
await sleep(5000); // pause de cinq secondes
setTimeout vs sleep : comprendre la différence
Une confusion fréquente chez les développeurs débutants est de considérer setTimeout comme un équivalent de sleep. Ce n'est absolument pas le cas. Voici pourquoi.
setTimeout planifie l'exécution d'une fonction après un délai, mais ne bloque pas l'exécution du code qui suit. Démonstration :
console.log('A');
setTimeout(() => console.log('B'), 1000);
console.log('C');
// Résultat : A, C, B (pas A, B, C)
Le message "C" s'affiche immédiatement après "A", sans attendre la seconde de délai. setTimeout a simplement planifié l'affichage de "B" pour plus tard. Il ne met rien en pause.
La fonction setInterval (settime js comme on le cherche parfois) fonctionne de manière similaire mais répète l'exécution à intervalles réguliers :
let compteur = 0;
const intervalle = setInterval(() => {
compteur++;
console.log(`Tick ${compteur}`);
if (compteur >= 5) {
clearInterval(intervalle);
console.log('Terminé');
}
}, 1000);
Ce code affiche un message chaque seconde pendant 5 secondes. Pour gérer la taille d'un tableau en JavaScript, vous pourriez combiner setInterval avec une vérification de longueur pour traiter des éléments par lots avec un délai entre chaque lot.
Voici la distinction fondamentale à retenir :
- setTimeout/setInterval : planifie un callback, le code continue de s'exécuter
- await sleep() : met en pause l'exécution de la fonction async, le code attend avant de continuer
En pratique, await sleep() utilise setTimeout en interne, mais l'enveloppe dans une Promise pour transformer un mécanisme de callback en une pause séquentielle du flux d'exécution.
Sleep synchrone en JavaScript : pourquoi l'éviter
Il est techniquement possible de créer un javascript sleep synchronous, c'est-à-dire un sleep qui bloque réellement l'exécution. Je le montre ici uniquement pour que vous compreniez pourquoi il ne faut jamais l'utiliser en production.
// NE PAS UTILISER EN PRODUCTION
function sleepSync(ms) {
const fin = Date.now() + ms;
while (Date.now() < fin) {
// Boucle active qui bloque tout
}
}
console.log('Avant');
sleepSync(3000); // Bloque TOUT pendant 3 secondes
console.log('Après');
Cette approche utilise une boucle active (busy loop) qui monopolise le processeur. Pendant ces 3 secondes, votre page web est complètement gelée. L'utilisateur ne peut ni scroller, ni cliquer, ni même sélectionner du texte. Le navigateur peut même afficher un avertissement "page ne répond pas".
Une variante légèrement moins catastrophique utilise Atomics.wait (disponible dans les Web Workers uniquement) :
// Uniquement dans un Web Worker, pas dans le thread principal
function sleepWorker(ms) {
const buffer = new SharedArrayBuffer(4);
const view = new Int32Array(buffer);
Atomics.wait(view, 0, 0, ms);
}
Mais même cette approche n'est utilisable que dans un Worker, pas dans le thread principal du navigateur. Selon la spécification ECMAScript sur Atomics.wait, l'appel lève une exception TypeError si exécuté sur le thread principal d'un agent qui a un document associé.
En résumé, le sleep synchrone pose trois problèmes majeurs :
- Gel de l'interface : aucune interaction utilisateur possible
- Consommation CPU : la boucle active consomme 100% d'un cœur
- Blocage des événements : les animations, les timers et les requêtes réseau sont suspendus
Cas pratiques et exemples avancés
Au fil de mes projets, j'ai accumulé plusieurs patterns d'utilisation du javascript sleep qui reviennent régulièrement. Voici les plus utiles.
Affichage progressif d'éléments
Pour animer l'apparition séquentielle d'éléments dans une interface, le sleep asynchrone est parfait :
async function afficherProgressivement(elements) {
for (const element of elements) {
element.classList.add('visible');
await sleep(200);
}
}
const cartes = document.querySelectorAll('.carte');
afficherProgressivement(cartes);
Chaque carte apparaît avec un décalage de 200ms, créant un effet visuel élégant. Pour des animations plus complexes, je recommande néanmoins d'utiliser requestAnimationFrame ou les animations CSS avec animation-delay.

Limitation de débit (rate limiting)
Quand on doit appeler une API avec une limite de requêtes par seconde, le sleep est indispensable :
async function traiterParLots(items, tailleLot, delaiMs) {
for (let i = 0; i < items.length; i += tailleLot) {
const lot = items.slice(i, i + tailleLot);
await Promise.all(lot.map(item => traiterItem(item)));
if (i + tailleLot < items.length) {
console.log(`Lot traité, pause de ${delaiMs}ms...`);
await sleep(delaiMs);
}
}
}
// Traiter 100 éléments par lots de 10, avec 1s entre chaque lot
traiterParLots(mesElements, 10, 1000);
Sleep avec annulation
Parfois, on a besoin d'annuler un sleep en cours. Voici une implémentation avec AbortController, que j'utilise souvent dans les composants React ou Vue :
function sleepCancellable(ms, signal) {
return new Promise((resolve, reject) => {
const timer = setTimeout(resolve, ms);
if (signal) {
signal.addEventListener('abort', () => {
clearTimeout(timer);
reject(new DOMException('Sleep annulé', 'AbortError'));
});
}
});
}
// Utilisation
const controller = new AbortController();
async function tacheLongue() {
try {
console.log('Début...');
await sleepCancellable(10000, controller.signal);
console.log('Terminé');
} catch (e) {
if (e.name === 'AbortError') {
console.log('Sleep interrompu');
}
}
}
tacheLongue();
// Pour annuler : controller.abort();
Ce pattern est particulièrement utile pour gérer le nettoyage lors du démontage d'un composant. Sans annulation, votre callback pourrait tenter de mettre à jour un composant déjà détruit, provoquant des fuites mémoire et des erreurs.
Utiliser les alertes JavaScript pour déboguer les timings
Pendant le développement, il peut être tentant d'utiliser alert() pour vérifier les délais de vos sleep. Attention cependant : alert() bloque le thread principal et fausse donc vos mesures de timing. Préférez toujours console.log avec performance.now() pour mesurer précisément vos temporisations.
Comparatif des méthodes de temporisation
Pour choisir la bonne approche selon votre situation, voici un tableau récapitulatif des principales méthodes de temporisation en JavaScript.
| Méthode | Type | Bloque le thread | Support navigateur | Cas d'usage recommandé |
|---|---|---|---|---|
| await sleep() (Promise + setTimeout) | Asynchrone | Non | Tous les navigateurs modernes | Pause séquentielle dans une fonction async |
| setTimeout | Asynchrone (callback) | Non | Universel | Exécuter du code après un délai unique |
| setInterval | Asynchrone (callback) | Non | Universel | Exécution répétée à intervalle régulier |
| requestAnimationFrame | Asynchrone | Non | Tous les navigateurs modernes | Animations fluides synchronisées à l'écran |
| Boucle active (while) | Synchrone | Oui | Universel | À éviter absolument |
| Atomics.wait | Synchrone | Oui (Worker uniquement) | Navigateurs récents | Web Workers avec SharedArrayBuffer |
| scheduler.postTask | Asynchrone | Non | Chrome 94+ | Prioritisation avancée des tâches |
Dans 95% des cas, la combinaison async/await avec la fonction sleep basée sur Promise est la solution idéale. Elle offre le meilleur compromis entre lisibilité du code, performance et compatibilité navigateur.
Erreurs courantes et bonnes pratiques
Après avoir accompagné de nombreux développeurs juniors et relu des centaines de code reviews, voici les erreurs que je rencontre le plus souvent avec le javascript sleep.
Erreur 1 : oublier await devant sleep()
// INCORRECT : le sleep est ignoré
async function mauvaisExemple() {
console.log('Début');
sleep(2000); // Promise non attendue !
console.log('Ceci s\'affiche immédiatement');
}
// CORRECT
async function bonExemple() {
console.log('Début');
await sleep(2000);
console.log('Ceci s\'affiche après 2 secondes');
}
Sans await, la Promise est créée puis immédiatement ignorée. C'est probablement l'erreur la plus fréquente. Certains linters comme ESLint avec la règle no-floating-promises (via typescript-eslint) peuvent détecter ce problème automatiquement.
Erreur 2 : utiliser sleep dans une boucle forEach
// INCORRECT : tous les sleep démarrent en même temps
[1, 2, 3].forEach(async (n) => {
await sleep(n * 1000);
console.log(n);
});
// CORRECT : utiliser for...of pour un traitement séquentiel
async function traiterSequentiellement() {
for (const n of [1, 2, 3]) {
await sleep(n * 1000);
console.log(n);
}
}
forEach ne respecte pas await dans son callback. Il lance toutes les itérations en parallèle. Utilisez for...of pour un traitement véritablement séquentiel.
Erreur 3 : ne pas gérer la précision du timer
Le délai passé à setTimeout est un minimum garanti, pas une valeur exacte. Le callback peut s'exécuter légèrement après le délai demandé, surtout si le thread principal est occupé. Pour des timings critiques (jeux vidéo, musique), préférez requestAnimationFrame ou l'API Web Audio qui offre une horloge haute résolution.
Erreur 4 : sleep comme solution à un problème de synchronisation
J'ai souvent vu des développeurs ajouter un sleep pour "attendre que le DOM soit prêt" ou "attendre qu'une requête soit terminée". C'est un anti-pattern. Si vous attendez un événement spécifique, utilisez les outils appropriés :
// MAUVAIS : attendre arbitrairement
await sleep(500);
const element = document.querySelector('.dynamique');
// BON : utiliser MutationObserver pour attendre un élément
function attendreElement(selecteur, timeout = 5000) {
return new Promise((resolve, reject) => {
const element = document.querySelector(selecteur);
if (element) return resolve(element);
const observer = new MutationObserver(() => {
const el = document.querySelector(selecteur);
if (el) {
observer.disconnect();
resolve(el);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => {
observer.disconnect();
reject(new Error(`Timeout : ${selecteur} non trouvé`));
}, timeout);
});
}
Bonnes pratiques résumées
- Toujours utiliser la version asynchrone du sleep
- Préférer
for...ofàforEachpour les boucles avec await - Implémenter l'annulation avec AbortController pour les sleep longs
- Ne jamais utiliser sleep comme substitut à un vrai mécanisme d'attente d'événement
- Nettoyer les timers avec
clearTimeoutquand un composant est détruit
Le développement web sur-mesure exige une maîtrise fine de ces mécanismes asynchrones. Chaque milliseconde compte pour l'expérience utilisateur, et une mauvaise gestion des temporisations peut transformer une application fluide en un cauchemar de performance.
À retenir
- Utilisez
const sleep = (ms) => new Promise(r => setTimeout(r, ms))comme fonction sleep universelle - Combinez toujours sleep avec async/await pour un code séquentiel et lisible
- Privilégiez for...of au lieu de forEach quand vous utilisez await dans une boucle
- Implémentez un AbortController pour pouvoir annuler les sleep longs dans vos composants
- N'utilisez jamais de boucle active (while) comme sleep synchrone en production
Questions fréquentes
Comment faire un sleep de 1 seconde en JavaScript ?
Créez la fonction const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) puis appelez await sleep(1000) dans une fonction async. Le paramètre est en millisecondes, donc 1000 correspond à une seconde. Le code suivant ne s'exécutera qu'après cette pause d'une seconde, sans bloquer le navigateur.
Pourquoi setTimeout ne fonctionne pas comme un sleep ?
setTimeout planifie un callback pour plus tard mais n'arrête pas l'exécution du code. Le code situé après setTimeout s'exécute immédiatement. Pour obtenir un vrai comportement de pause, il faut envelopper setTimeout dans une Promise et utiliser await, ce qui permet de suspendre l'exécution de la fonction async jusqu'à la résolution de la Promise.
Peut-on faire un sleep synchrone en JavaScript ?
Techniquement oui, avec une boucle while qui tourne jusqu'à ce que le délai soit écoulé. Mais c'est une très mauvaise pratique : cela bloque entièrement le thread principal, gèle l'interface utilisateur et consomme 100% du CPU pendant la durée du sleep. Le navigateur peut même afficher un avertissement "page ne répond pas". Utilisez toujours la version asynchrone avec async/await.
Comment annuler un sleep en cours en JavaScript ?
Utilisez un AbortController. Créez une version modifiée de la fonction sleep qui accepte un signal d'annulation : si le signal est déclenché via controller.abort(), le clearTimeout est appelé et la Promise est rejetée avec une erreur AbortError. Ce pattern est particulièrement utile dans les composants React ou Vue pour éviter les fuites mémoire lors du démontage.
Quelle est la précision de setTimeout en JavaScript ?
Le délai de setTimeout est un minimum garanti, pas une valeur exacte. En pratique, la résolution est d'environ 4ms dans les navigateurs modernes (conformément à la spécification HTML5). Si le thread principal est occupé, le callback peut être retardé davantage. Pour des timings précis (animations, audio), préférez requestAnimationFrame ou l'API Web Audio qui disposent de mécanismes de synchronisation haute résolution.
Comment utiliser sleep dans une boucle en JavaScript ?
Utilisez impérativement une boucle for...of avec await, jamais forEach. La méthode forEach ne respecte pas await dans son callback et lance toutes les itérations simultanément. Avec for...of, chaque itération attend la fin du sleep avant de passer à la suivante : for (const item of items) { await sleep(500); traiter(item); }.
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.