Maison  >  Article  >  interface Web  >  Pourquoi l'ordre d'exécution de la promesse ne correspond-il pas aux attentes en JavaScript ?

Pourquoi l'ordre d'exécution de la promesse ne correspond-il pas aux attentes en JavaScript ?

Patricia Arquette
Patricia Arquetteoriginal
2024-10-25 08:01:28398parcourir

Why Doesn't the Order of Promise Execution Match Expectations in JavaScript?

Quel est l'ordre d'exécution dans les promesses JavaScript ?

Problème :

L'extrait suivant démontre l'utilisation de JavaScript promesses, et l'ordre d'exécution est intrigant.

<code class="javascript">Promise.resolve('A')
  .then(function(a){console.log(2, a); return 'B';})
  .then(function(a){
     Promise.resolve('C')
       .then(function(a){console.log(7, a);})
       .then(function(a){console.log(8, a);});
     console.log(3, a);
     return a;})
  .then(function(a){
     Promise.resolve('D')
       .then(function(a){console.log(9, a);})
       .then(function(a){console.log(10, a);});
     console.log(4, a);})
  .then(function(a){
     console.log(5, a);});
console.log(1);
setTimeout(function(){console.log(6)},0);</code>

Le résultat indique que l'ordre d'exécution est :

1
2 "A"
3 "B"
7 "C"
4 "B"
8 undefined
9 "D"
5 undefined
10 undefined
6

La question posée est de savoir pourquoi l'ordre d'exécution n'est pas 1, 2 , 3, 4..., et en quoi l'espérance de 1, 2, 3, 4... diffère-t-elle du résultat ?

Réponse :

Commentaires :

L'exécution de promesses dans un gestionnaire .then() sans les renvoyer du rappel .then() crée une nouvelle séquence de promesses non attachée qui ne se synchronise en aucun cas avec les promesses parentes. chemin. Ceci est généralement considéré comme un bug et certains moteurs de promesses émettent des avertissements lorsque cela se produit, car ce n'est généralement pas le comportement prévu. Un cas d'utilisation valide pourrait être une opération « lancer et oublier » où ni les erreurs ni la synchronisation ne sont un problème.

Les promesses Promise.resolve() au sein des gestionnaires .then() créent de nouvelles chaînes de promesses qui s'exécutent indépendamment du parent. chaîne. Avec les opérations asynchrones réelles, telles que les appels AJAX, il n'existe aucun comportement prévisible pour les chaînes de promesses indépendantes et déconnectées. Le moment de l'achèvement est indéterminé, comme le lancement de quatre appels AJAX en parallèle dont l'ordre d'achèvement est inconnu. Dans le code fourni, toutes les opérations sont synchrones, ce qui entraîne un comportement cohérent, mais il ne faut pas s'y fier car l'objectif de conception des promesses est une exécution asynchrone.

Résumé :

  1. Tous les gestionnaires .then() sont invoqués de manière asynchrone une fois le thread d'exécution actuel terminé. Cette cohérence inclut les promesses résolues de manière synchrone, telles que Promise.resolve().then(...), pour éviter les bogues de timing.
  2. Il n'y a pas d'ordre spécifié pour les gestionnaires setTimeout() par rapport aux gestionnaires .then() programmés. Alors que l'implémentation utilisée place un gestionnaire .then() en attente avant un setTimeout() en attente, la spécification Promises/A permet de planifier avant ou après setTimeout().
  3. Les chaînes de promesses indépendantes n'ont pas d'exécution prévisible. order.
  4. Si l'ordre d'exécution est crucial, évitez de créer des courses dépendantes de détails de mise en œuvre minutieux. Au lieu de cela, liez les chaînes de promesses pour forcer un ordre spécifique.
  5. Évitez de créer des chaînes de promesses indépendantes dans les gestionnaires .then(), sauf s'il s'agit d'un scénario « tirer et oublier ».

Analyse ligne par ligne :

  1. La chaîne de promesse initiale est initiée et un gestionnaire .then() est attaché. Comme Promise.resolve() se résout instantanément, le premier gestionnaire .then() est programmé pour s'exécuter une fois le thread JavaScript actuel terminé. Les gestionnaires .then() suivants au niveau supérieur de la chaîne après le premier et ne s'exécuteront qu'une fois le premier terminé.
  2. Le setTimeout() est exécuté à la fin du thread d'exécution et une minuterie est programmée.
  3. Une fois l'exécution synchrone terminée, la file d'attente des événements exécute les tâches restantes.
  4. Le gestionnaire .then() défini dans la ligne 1 s'exécute et '2 "A"' est enregistré.
  5. Le gestionnaire .then() suivant est invoqué et une nouvelle chaîne de promesses indépendante est créée avec un gestionnaire .then() programmé pour s'exécuter lorsque le thread d'exécution actuel se termine. Ce gestionnaire imprime '3 "B"' avant l'exécution du gestionnaire .then() de la chaîne enfant, qui imprime '7 "C"'.
  6. Le gestionnaire .then() défini à la ligne 12 est ensuite invoqué, et encore une fois, une nouvelle chaîne de promesses est créée, planifiant un gestionnaire .then(). '4 "B"' est enregistré à partir de ce gestionnaire.
  7. Le gestionnaire .then() programmé de la chaîne enfant est exécuté, imprimant '8 non défini'.
  8. Le gestionnaire .then() défini à la ligne 19 est ensuite invoqué et une autre chaîne de promesses indépendante est créée, planifiant un gestionnaire .then(). « 5 non défini » est imprimé à partir de ce gestionnaire.
  9. Enfin, le gestionnaire .then() défini à la ligne 15 est invoqué et « 10 non défini » est imprimé.
  10. Le setTimeout() s'exécute dernier.

Conclusion :

L'absence d'ordre spécifique dans les exécutions de promesses Promise.resolve() au sein des gestionnaires .then(), ainsi que le l'indétermination de la planification du gestionnaire .then() par rapport à setTimeout() pour divers moteurs, souligne l'importance de contrôler l'ordre d'exécution grâce à l'enchaînement des promesses.

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!

Déclaration:
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