Maison > interface Web > js tutoriel > Comment gérer plusieurs promesses simultanément avec Promise.all()

Comment gérer plusieurs promesses simultanément avec Promise.all()

Mary-Kate Olsen
Libérer: 2024-11-09 05:33:02
original
351 Les gens l'ont consulté

La programmation asynchrone en JavaScript permet d'exécuter des opérations gourmandes en ressources en arrière-plan sans interrompre le thread principal. Les opérations telles que les appels API et les processus de fichiers font partie des opérations qui doivent être exécutées de manière asynchrone.

Promesses. all() est une fonction puissante qui permet de gérer ces opérations simultanément. Cet article expliquera comment gérer plusieurs promesses simultanément avec Promise.all()

Plongeons-nous.

Qu'est-ce qu'une promesse

Une promesse est un objet qui représente l'échec ou l'achèvement éventuel d'un événement asynchrone. Regardons une promesse simple.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion

Une promesse prend une fonction avec deux paramètres, résoudre et rejeter. Dans notre exemple, la promesse sera résolue si l'opération réussit (c'est-à-dire si l'ID utilisateur === 1. Si l'opération échoue, la promesse sera rejetée.

Le cycle de vie d'une promesse commence à l'état en attente, et elle finira par être remplie ou rejetée. Actuellement, la promesse est en attente. Pour consommer la promesse, nous appelons .then() pour gérer le résultat.

Le résultat sera soit les données utilisateur (si remplies), soit une erreur (si rejetée).

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copier après la connexion
Copier après la connexion
Copier après la connexion

Puisque l'opération est réussie, la promesse sera résolue.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copier après la connexion
Copier après la connexion

si nous modifions la valeur de userId, la promesse sera rejetée et vous obtiendrez l'erreur Utilisateur introuvable

Supposons que vous ayez plusieurs promesses, vous géreriez chaque promesse indépendamment comme ceci :

const promise1 = new Promise((resolve, reject) => resolve(1));
const promise2 = new Promise((resolve, reject) => resolve(2));
const promise3 = new Promise((resolve, reject) => resolve(3));
promise1
  .then((value) => {
    console.log(value);
    promise2
      .then((value) => {
        console.log(value);
        promise3
          .then((value) => {
            console.log(value);
          })
          .catch((err) => {
            console.log("promise3 error", err);
          });
      })
      .catch((err) => {
        console.log("promise2 error", err);
      });
  })
  .catch((err) => {
    console.log("promise1 error", err);
  });
Copier après la connexion

Il y a quelques problèmes potentiels qui découleront de l'exécution ci-dessus :

  • Chaque promesse s'exécute une fois la précédente terminée. promise2 démarrera après la résolution de promise1 et promise3 démarrera après la résolution de promise2 ; Cela ralentit l'exécution.

  • La structure imbriquée dans le chaînage .then entraîne un « enfer de rappel », ​​rendant le code plus difficile à lire et à maintenir.

  • Chaque erreur est traitée indépendamment, ce qui ajoute à la complexité.

Une meilleure approche serait d'utiliser Promise.all(), qui permet aux promesses de s'exécuter en même temps, améliorant ainsi les performances et la gestion des erreurs

Amélioration des opérations asynchrones avec Promise.all()

Promise.all() prend un itérable de promesses et renvoie une seule promesse. La syntaxe ressemble à ceci :

Promise.all(iterable)
Copier après la connexion

Si nous utilisons Promise.all() Dans notre exemple précédent, nous avons quelque chose comme ceci :

Promise.all([promise1, promise2, promise3])
  .then((values) => {
    console.log(values);
  })
  .catch((err) => {
    console.log("promise all error", err);
  });
Copier après la connexion

Comme vous pouvez le constater, cette approche est plus claire et plus facile à comprendre.

JavaScript est un langage monothread, ce qui signifie que chaque morceau de code attend que le précédent soit terminé avant de passer au suivant.

Donc, si JavaScript est monothread, comment Promise.all() gère-t-il plusieurs promesses ?

Promise.all() fonctionne selon le principe de concurrence, ce qui signifie que toutes les promesses ne commenceront pas nécessairement à s'exécuter au même moment, mais seront initiées sans attendre qu'une promesse soit terminée avant de commencer la suivante.

Promise.all() ne se résout que lorsque toutes les promesses de l'itérable sont remplies. Cependant, si l'une des promesses de l'itérable est rejetée, Promise.all() la rejettera immédiatement et ignorera le résultat des promesses restantes.

Exemples pratiques

Promise.all() excelle dans les scénarios où vous devez effectuer plusieurs opérations asynchrones indépendantes et attendre qu'elles soient toutes terminées avant de continuer.

Examinons quelques-uns de ces exemples dans lesquels Promise.all() peut être utilisé pour améliorer l'efficacité des applications du monde réel.

1.Récupération de données à partir de plusieurs API

Considérez un scénario dans lequel vous travaillez sur une application qui récupère simultanément des données de deux API différentes.

Essayons de récupérer les données de manière séquentielle à partir de plusieurs API et enregistrons également le temps nécessaire pour terminer la demande.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion

Voici le résultat :

How to Manage Multiple promises concurrently with Promise.all()

Le temps de traitement de la demande est de 50,36 ms. Ce temps d'exécution peut être amélioré. Pour illustrer les avantages de la concurrence, comparons l'approche utilisant Promise.all()

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copier après la connexion
Copier après la connexion
Copier après la connexion

Ici, nous utilisons Promise.all() pour exécuter plusieurs opérations asynchrones simultanément. Promise.all() prendra un tableau de promesses et renverra une seule promesse lorsque toutes les promesses seront résolues.

Voici le résultat.

How to Manage Multiple promises concurrently with Promise.all()

D'après le résultat, nous pouvons voir que l'utilisation de Promise.all() est légèrement plus efficace : cette amélioration se produit car Promise.all() permet aux deux opérations de démarrer simultanément, plutôt que d'attendre que l'une se termine avant de démarrer l'autre.

Dans les applications du monde réel avec des opérations plus complexes ou des appels d'API supplémentaires, les gains de performances liés à l'utilisation de Promise.all() peuvent être encore plus significatifs.

Cependant, si vous souhaitez attendre que toutes les promesses soient réglées, qu'elles soient remplies ou rejetées, vous pouvez utiliser Promise.allSettled()

  1. Envoi de plusieurs morceaux de données Supposons que vous disposiez d'un ensemble de morceaux de texte qui représentent les commentaires ou les avis des clients et que vous deviez analyser le sentiment de chaque morceau en l'envoyant à une API externe pour analyse.

Dans ce cas, toutes les données doivent être envoyées en même temps. Dans ce cas, vous pouvez utiliser Promise.all() et envoyer toutes les requêtes simultanément, puis attendre qu'elles soient toutes résolues avant d'obtenir les résultats.

Par exemple, supposons que nous devions analyser cet exemple de données :

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans ce cas, toutes les données doivent être envoyées en même temps ; l’envoi séquentiel de données prendra beaucoup de temps. Au lieu de cela, nous utiliserons Promise.all() pour lancer plusieurs appels API simultanément.

Vous aurez quelque chose comme ceci :

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copier après la connexion
Copier après la connexion
Copier après la connexion

3. Lecture et traitement de plusieurs fichiers simultanément.

Supposons que vous disposiez d'une application qui accepte les téléchargements groupés des utilisateurs. Après avoir pris toutes les mesures nécessaires pour valider les fichiers, vous pouvez utiliser Promise.all() pour effectuer plusieurs lectures de fichiers en parallèle. C'est bien plus efficace que de lire chaque fichier un par un de manière séquentielle.

Sans Promise.all(), vous devrez attendre que chaque fichier soit lu complètement avant de lire le fichier suivant. Cela entraînerait un temps de traitement plus long, surtout si vous avez un plus grand nombre de fichiers.

Cependant, avec Promise.all(), toutes les opérations de lecture de fichiers sont lancées simultanément, ce qui entraîne un gain de temps considérable et une excellente expérience utilisateur.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copier après la connexion
Copier après la connexion

Il est également important de noter que lorsque vous lisez simultanément de nombreux fichiers volumineux, vous devez être conscient des considérations potentielles en matière de mémoire.

Résumé

En conclusion, Promise.all() offre de nombreux avantages qui sont résumés ci-dessous

Cleaner Code : Promise.all() rend votre code plus facile à comprendre puisque vous n'avez pas de chaînes .then() imbriquées. Les requêtes sont traitées dans un seul bloc .then().

Efficace : En effectuant des requêtes simultanément, les performances globales de votre application s'améliorent, car le temps total requis pour récupérer les données est réduit.

Améliorez votre JavaScript

Recevez des conseils JavaScript pratiques et des extraits de code dans votre boîte de réception. Rejoignez 1 000 développeurs qui écrivent un meilleur code.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal