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

Publié le 21 juin 2024
Dimitri Dumont avatar
Dimitri Dumont
Développeur front-end

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. Sachez tout de même que Promise.all est une méthode JavaScript native, et 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é à gérer plusieurs opérations asynchrones simultanément est l'une des solutions qui peut être utilisée 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, Promise.all permet d'exécuter plusieurs requêtes en parallèle, réduisant ainsi le temps d'attente total.
  • Gestion efficace des erreurs : Promise.all rejette la promesse principale dès que l'une des promesses passées en paramètre est rejetée, permettant de détecter et de gérer les erreurs plus rapidement.
  • Code plus propre et maintenable : En centralisant la gestion des promesses, Promise.all permet d'éviter les chaînes de promesses complexes et imbriquées, rendant le code plus lisible et maintenable.

Les inconvénients de Promise.all

Bien que Promise.all présente de nombreux avantages, cette méthode comporte également des inconvénients à prendre en compte :

  • Rejet global : Si une seule promesse échoue, Promise.all rejette l'ensemble des promesses, ce qui peut être problématique si vous avez besoin des résultats des autres promesses.
  • Charge réseau accrue : Exécuter plusieurs requêtes simultanément peut surcharger le réseau, surtout si les requêtes concernent de grandes quantités de données ou sont envoyées à des serveurs différents.
  • Gestion des ressources : L'utilisation excessive de Promise.all peut entraîner une utilisation inefficace des ressources, surtout si les promesses impliquent des opérations lourdes en calcul ou en mémoire.

Exemples d'utilisation

Voici quelques exemples pratiques d'utilisation de Promise.all pour optimiser les performances dans vos projets front-end (Javascript, React, Next.js, etc.) :

Exemple simple

Supposons que vous devez récupérer les informations d'un utilisateur, ses amis et ses photos depuis différentes API dans un projet front-end (React, Next.js, etc.). Faire ces requêtes séquentiellement prendrait un temps considérable et réduirait l'efficacité de votre application.

1type User = {
2 id: number;
3 name: string;
4}
5
6type Friend = {
7 id: number;
8 name: string;
9}
10
11type Photo = {
12 id: number;
13 url: string;
14}
15
16
17const getUserData = (): Promise<User> => fetch('/api/user').then(response => response.json());
18const getUserFriends = (userId: number): Promise<Friend[]> => fetch(`/api/user/${userId}/friends`).then(response => response.json());
19const getUserPhotos = (userId: number): Promise<Photo[]> => fetch(`/api/user/${userId}/photos`).then(response => response.json());
20
21const userId = 1;
22
23Promise.all([
24 getUserData(),
25 getUserFriends(userId),
26 getUserPhotos(userId)
27]).then(([userData, friends, photos]) => {
28 console.log('User Data:', userData);
29 console.log('Friends:', friends);
30 console.log('Photos:', photos);
31}).catch(error => {
32 console.error('An error occurred:', error);
33});

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. Cela permet de réduire le temps total nécessaire pour obtenir toutes les données, améliorant ainsi la réactivité de l'application.

hexa web logo
Hexa web
Des conseils pour un projet web ?
Nous contacter

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. Faire ces appels API de manière séquentielle entraîne des temps de chargement longs dans votre application Next.js.

app/product/[productId]/page.tsx
1import { GetServerSidePropsContext } from 'next';
2import { Suspense } from 'react';
3
4type Product = {
5 id: number;
6 name: string;
7 description: string;
8 price: number;
9}
10
11type Review = {
12 id: number;
13 content: string;
14 rating: number;
15}
16
17type Recommendation = {
18 id: number;
19 name: string;
20 price: number;
21}
22
23const getProductDetails = async (productId: number): Promise<Product> => {
24 const response = await fetch(`https://api.example.com/product/${productId}`);
25 return response.json();
26};
27
28const getProductReviews = async (productId: number): Promise<Review[]> => {
29 const response = await fetch(`https://api.example.com/product/${productId}/reviews`);
30 return response.json();
31};
32
33const getProductRecommendations = async (productId: number): Promise<Recommendation[]> => {
34 const response = await fetch(`https://api.example.com/product/${productId}/recommendations`);
35 return response.json();
36};
37
38export async function generateMetadata({ params }: { params: { productId: string } }) {
39 const productId = parseInt(params.productId, 10);
40 const product = await getProductDetails(productId);
41 return { title: product.name };
42}
43
44export default async function ProductPage({ params }: { params: { productId: string } }) {
45 const productId = parseInt(params.productId, 10);
46
47 const [product, reviews, recommendations] = await Promise.all([
48 getProductDetails(productId),
49 getProductReviews(productId),
50 getProductRecommendations(productId),
51 ]);
52
53 return (
54 <div>
55 <h1>{product.name}</h1>
56 <p>{product.description}</p>
57 <p>Price: ${product.price}</p>
58
59 <h2>Customer Reviews</h2>
60 <ul>
61 {reviews.map((review) => (
62 <li key={review.id}>{review.content} - {review.rating} stars</li>
63 ))}
64 </ul>
65
66 <h2>Recommended Products</h2>
67 <ul>
68 {recommendations.map((recommendation) => (
69 <li key={recommendation.id}>{recommendation.name} - ${recommendation.price}</li>
70 ))}
71 </ul>
72 </div>
73 );
74}
75

Dans cet exemple, nous utilisons les server components de Next.js pour rendre 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 de produits sont effectués en parallèle grâce à Promise.all.

Cela garantit que les données sont chargées simultanément, réduisant ainsi le temps d'attente et améliorant l'expérience utilisateur.

Conclusion

Promise.all est un outil puissant et important à connaitre pour optimiser les performances des applications front-end React & Next.js en exécutant des opérations asynchrones en parallèle.

Cependant, il est essentiel de bien comprendre ses inconvénients et de l'utiliser de manière judicieuse pour éviter les problèmes de performances et de gestion des erreurs.

En appliquant les bonnes pratiques et en tenant compte des contraintes spécifiques à chaque projet, vous pouvez profitez des bénéfices de Promise.all dans votre SaaS, votre application web ou votre site e-commerce.

Échangeons sur votre projet web

Présentez-nous votre projet web, nous vous recontacterons dans les prochaines 24h.