Aller au contenu principal

Publié le · Mis à jour le 2 octobre 2026

Comment utiliser Promise.all pour optimiser les performances dans un projet front-end ?

Dimitri Dumont
Dimitri Dumont

Développeur React & Next.js freelance

Dans cet article, nous allons découvrir ce qu'est Promise.all, pourquoi l'utiliser, ses avantages et inconvénients, et comment l'utiliser pour optimiser les performances dans un projet front-end avec React, Next.js & TypeScript. Promise.all est une méthode JavaScript native : elle peut être utilisée dans n'importe quel projet, front-end comme back-end.

Qu'est-ce que Promise.all ?

Promise.all est une méthode JavaScript qui permet de gérer plusieurs promesses de manière concurrente. Elle prend en entrée un tableau de promesses et renvoie une seule promesse qui se résout lorsque toutes les promesses du tableau sont résolues, ou rejette si l'une des promesses est rejetée.

Cette capacité à attendre plusieurs opérations asynchrones en même temps est l'une des solutions pour optimiser les performances dans des projets front-end complexes, tels que les SaaS, les sites e-commerce et les applications web.

Pourquoi utiliser Promise.all ?

  • Réduction du temps d'attente global : plutôt que d'attendre que chaque requête se termine avant de commencer la suivante, les requêtes s'exécutent en parallèle. Trois requêtes de 200 ms prennent environ 200 ms au lieu de 600 ms.
  • Détection rapide des erreurs : Promise.all rejette la promesse principale dès que l'une des promesses passées en paramètre est rejetée.
  • Code plus lisible : les résultats arrivent dans un seul tableau, dans l'ordre des promesses, ce qui évite les chaînes de promesses imbriquées.

Les inconvénients de Promise.all

Cette méthode comporte également des inconvénients à prendre en compte :

  • Rejet global : si une seule promesse échoue, Promise.all rejette l'ensemble, ce qui pose problème si vous avez besoin des résultats des autres promesses. Les autres requêtes ne sont pas annulées pour autant : elles continuent de s'exécuter, mais leurs résultats sont perdus.
  • Charge accrue : lancer un grand nombre de requêtes simultanément peut saturer l'API appelée ou déclencher ses limites de débit.
  • Attente de la plus lente : rien n'est disponible tant que la promesse la plus lente n'est pas résolue. Une seule requête lente retarde tout l'affichage.

Exemples d'utilisation

Voici deux exemples pratiques d'utilisation de Promise.all dans un projet front-end :

Exemple simple

Supposons que vous devez récupérer les informations d'un utilisateur, ses amis et ses photos depuis différentes API. Faire ces requêtes séquentiellement additionnerait leurs temps de réponse.

type User = {
  id: number;
  name: string;
}
 
type Friend = {
  id: number;
  name: string;
}
 
type Photo = {
  id: number;
  url: string;
}
 
 
const getUserData = (): Promise<User> => fetch('/api/user').then(response => response.json());
const getUserFriends = (userId: number): Promise<Friend[]> => fetch(`/api/user/${userId}/friends`).then(response => response.json());
const getUserPhotos = (userId: number): Promise<Photo[]> => fetch(`/api/user/${userId}/photos`).then(response => response.json());
 
const userId = 1;
 
Promise.all([
  getUserData(),
  getUserFriends(userId),
  getUserPhotos(userId)
]).then(([userData, friends, photos]) => {
  console.log('User Data:', userData);
  console.log('Friends:', friends);
  console.log('Photos:', photos);
}).catch(error => {
  console.error('An error occurred:', error);
});

Dans cet exemple, les appels API pour récupérer les données utilisateur, les amis et les photos sont effectués en parallèle grâce à Promise.all. Le temps total pour obtenir toutes les données est celui de la requête la plus lente.

Utilisation de Promise.all avec Next.js

Prenons l'exemple d'une page de produit e-commerce qui doit charger les détails du produit, les avis des clients et les produits recommandés. Dans un Server Component, chaque await écrit l'un après l'autre bloque le suivant.

app/product/[productId]/page.tsx
type Product = {
  id: number;
  name: string;
  description: string;
  price: number;
}
 
type Review = {
  id: number;
  content: string;
  rating: number;
}
 
type Recommendation = {
  id: number;
  name: string;
  price: number;
}
 
type Props = {
  params: Promise<{ productId: string }>;
}
 
const getProductDetails = async (productId: number): Promise<Product> => {
  const response = await fetch(`https://api.example.com/product/${productId}`);
  return response.json();
};
 
const getProductReviews = async (productId: number): Promise<Review[]> => {
  const response = await fetch(`https://api.example.com/product/${productId}/reviews`);
  return response.json();
};
 
const getProductRecommendations = async (productId: number): Promise<Recommendation[]> => {
  const response = await fetch(`https://api.example.com/product/${productId}/recommendations`);
  return response.json();
};
 
export async function generateMetadata({ params }: Props) {
  const { productId } = await params;
  const product = await getProductDetails(parseInt(productId, 10));
  return { title: product.name };
}
 
export default async function ProductPage({ params }: Props) {
  const productId = parseInt((await params).productId, 10);
 
  const [product, reviews, recommendations] = await Promise.all([
    getProductDetails(productId),
    getProductReviews(productId),
    getProductRecommendations(productId),
  ]);
 
  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <p>Price: ${product.price}</p>
 
      <h2>Customer Reviews</h2>
      <ul>
        {reviews.map((review) => (
          <li key={review.id}>{review.content} - {review.rating} stars</li>
        ))}
      </ul>
 
      <h2>Recommended Products</h2>
      <ul>
        {recommendations.map((recommendation) => (
          <li key={recommendation.id}>{recommendation.name} - ${recommendation.price}</li>
        ))}
      </ul>
    </div>
  );
}

Dans cet exemple, un Server Component de Next.js rend une page de produit e-commerce. Les appels API pour récupérer les détails du produit, les avis des clients et les recommandations sont effectués en parallèle grâce à Promise.all.

Depuis Next.js 15, params est une promesse, d'où le await params. Sur Next.js 13 et 14, params est un objet et se lit directement.

Quand préférer Suspense à Promise.all

Promise.all attend la requête la plus lente avant d'afficher quoi que ce soit. Si les recommandations mettent deux secondes à répondre, le titre du produit attend lui aussi deux secondes.

Quand une partie de la page est nettement plus lente que le reste, il vaut mieux la déplacer dans son propre Server Component, enveloppé dans <Suspense>. Next.js envoie alors le reste de la page immédiatement et diffuse cette partie dès qu'elle est prête. Les deux approches se combinent : Promise.all pour les données indispensables au premier affichage, Suspense pour le contenu secondaire.

FAQ

Quelle est la différence entre Promise.all et Promise.allSettled ?

Promise.all échoue dès qu'une promesse est rejetée, tandis que Promise.allSettled attend toutes les promesses. Promise.allSettled retourne un tableau d'objets { status: 'fulfilled', value } ou { status: 'rejected', reason } pour chaque promesse, ce qui permet de traiter les succès et les échecs indépendamment.

Promise.all exécute-t-il vraiment les promesses en parallèle ?

Promise.all ne lance rien : les opérations démarrent au moment où les promesses sont créées, et Promise.all se contente d'attendre leurs résultats. JavaScript reste mono-thread. Les opérations d'entrée-sortie (requêtes HTTP, accès fichiers) progressent en parallèle au niveau du système, alors que les calculs purement CPU restent séquentiels. Le gain vient de la réduction du temps d'attente cumulé des opérations d'entrée-sortie.

Comment limiter le nombre de requêtes simultanées avec Promise.all ?

Promise.all ne propose pas de limite native. Une solution consiste à découper le tableau en lots et à exécuter les lots l'un après l'autre. Des librairies comme p-limit ou p-map offrent cette fonctionnalité avec une API simple.

Faut-il utiliser Promise.all dans les Server Components Next.js ?

Oui, c'est le moyen le plus direct d'éviter les requêtes en cascade. React déduplique les appels fetch identiques (même URL, mêmes options) pendant le rendu d'une requête : dans l'exemple plus haut, getProductDetails est appelée dans generateMetadata et dans la page, mais l'API n'est interrogée qu'une fois. Pour les fonctions qui ne passent pas par fetch (ORM, SDK), React.cache() joue le même rôle.

Conclusion

Promise.all est un outil important à connaître pour optimiser les performances des applications React & Next.js en exécutant des opérations asynchrones en parallèle.

Ses limites sont à garder en tête : une seule erreur rejette l'ensemble, et tout attend la promesse la plus lente. Promise.allSettled répond au premier cas, Suspense au second.

Dimitri Dumont

Dimitri Dumont

Développeur React & Next.js freelance depuis 8 ans, 33 entreprises accompagnées depuis 2018. J'écris ici ce que je constate en mission : un produit ralentit presque toujours pour les mêmes raisons, une architecture posée dans l'urgence, pas de tests, une mise en production qui fait peur. Mon travail consiste à construire des produits qui n'en arrivent pas là, et à remettre sur pied ceux qui y sont déjà. Mon parcours

La suite

Ce que ça donne sur votre code

Lire un article et lire une vraie codebase sont deux exercices différents. Je lis la vôtre et je vous dis ce qui ralentit, ce que ça coûte de le corriger, et dans quel ordre.

Articles similaires