Maison  >  Article  >  interface Web  >  Une analyse approfondie des raisons pour lesquelles Promise est plus rapide que setTimeout()

Une analyse approfondie des raisons pour lesquelles Promise est plus rapide que setTimeout()

青灯夜游
青灯夜游avant
2021-02-04 16:04:401610parcourir

Pourquoi Promise est-il plus rapide que setTimeout() ? L'article suivant analysera les raisons pour vous. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.

Une analyse approfondie des raisons pour lesquelles Promise est plus rapide que setTimeout()

Recommandations associées : "Tutoriel vidéo javascript"

Expérience

Faisons une expérience. Qu'est-ce qui s'exécute plus rapidement : une promesse immédiatement résolue ou un setTimeout immédiat (c'est-à-dire un setTimeout de 0 milliseconde) ?

Promise.resolve(1).then(function resolve() {
  console.log('Resolved!');
});

setTimeout(function timeout() {
  console.log('Timed out!');
}, 0);

// 'Resolved!'
// 'Timed out!'

promise.resolve(1) est une fonction statique qui renvoie un promise immédiatement résolu. setTimeout(callback, 0)Exécutez la fonction de rappel avec un délai de 0毫秒.

Nous pouvons voir qu'en imprimant 'Resolved!' d'abord, puis en imprimant Timeout completed!, la promesse qui se résout immédiatement est plus rapide que l'immédiate setTimeout.

est dû au fait que Promise.resolve(true).then(...) est appelé avant setTimeout(..., 0), le processus de promesse sera-t-il donc plus rapide ? Bonne question.

Donc, nous modifions légèrement les conditions expérimentales et appelons setTimeout(..., 0) en premier :

setTimeout(function timeout() {
  console.log('Timed out!');
}, 0);

Promise.resolve(1).then(function resolve() {
  console.log('Resolved!');
});

// 'Resolved!'
// 'Timed out!'

setTimeout(..., 0) est appelé avant Promise.resolve(true).then(...). Cependant, imprimez Resolved! d'abord, puis 'Timed out!'.

Pourquoi ça ?

2. Boucle d'événement

Les questions liées au JS asynchrone peuvent trouver une réponse en étudiant la boucle d'événement. Passons en revue les principaux composants du fonctionnement du JS asynchrone.

[Le transfert d'image par lien externe a échoué, le site source peut avoir un mécanisme anti-sangsue, il est recommandé de sauvegarder l'image et de la télécharger directement (img-Lt9zVHTf-1611275604640)(/img/bVcMQaI)]

La pile d'appels est une structure LIFO (dernier entré, premier sorti) qui stocke le contexte d'exécution créé lors de l'exécution du code. En termes simples, la pile d'appels exécute ces fonctions.

L'API Web est l'endroit où les opérations asynchrones (récupération de requêtes, promesses, minuteries) et leurs rappels attendent d'être terminés.

**file d'attente des tâches (file d'attente des tâches) est une structure FIFO (premier entré, premier sorti)** qui enregistre les rappels pour les opérations asynchrones prêtes à être exécutées. Par exemple, une fonction de rappel d'un setTimeout() qui expire ou un gestionnaire d'événements de clic sur un bouton prêt à être exécuté sont tous mis en file d'attente dans la file d'attente des tâches.

**job queue** est une structure FIFO (premier entré, premier sorti), qui enregistre les rappels de promise prêts à être exécutés. Par exemple, le rappel resolve ou reject d'une promesse terminée est mis en file d'attente dans la file d'attente des tâches.

Enfin, la boucle d'événements écoute en permanence si la pile d'appels est vide. Si la pile d'appels est vide, la boucle d'événements examine la file d'attente des tâches ou la file d'attente des tâches et distribue tous les rappels prêts à être exécutés sur la pile d'appels.

3. File d'attente des tâches et file d'attente des tâches

Regardons cette expérience du point de vue de la boucle d'événements, et j'analyserai l'exécution du code étape par étape.

A) La pile d'appels exécute setTimeout(..., 0) et planifie une minuterie timeout()Le rappel est stocké dans l'API Web :

[Le transfert d'image du lien externe a échoué, le site source a peut-être échoué. mécanisme de protection anti-hotlink, il est recommandé de sauvegarder l'image et de la télécharger directement (img-SLk0AUa5-1611275604642)(/img/bVcMQdg)]

[Le transfert de l'image du lien externe a échoué, le site source a peut-être un mécanisme anti-sangsue, il est recommandé de sauvegarder l'image Upload directement (img-Zr7usYTK-1611275604643)(/img/bVcMQc9)]

B) La pile d'appels exécute Promise.resolve(true).then(resolve) et planifie un promise solution. resolved()Le rappel est stocké dans l'API Web :

[Le transfert de l'image du lien externe a échoué. Le site source peut avoir un mécanisme anti-sangsue. Il est recommandé de sauvegarder l'image et de la télécharger directement (img. -JTwSnLYS-1611275604646)(/img/ bVcMQdh)]

[Le transfert de l'image du lien externe a échoué. Le site source peut avoir un mécanisme anti-sangsue. Il est recommandé de sauvegarder l'image et de la télécharger directement (img. -k5cRhqzN-1611275604648)(/img/bVcMQdi)]

C) La promesse est résolue immédiatement et le minuteur est exécuté immédiatement. De cette façon, le rappel du minuteur timeout() entre dans la file d'attente des tâches et le promise rappel resolve() entre dans la file d'attente des travaux

[Le transfert d'image du lien externe a échoué. Le site source peut avoir un anti-. mécanisme de sangsue. Il est recommandé de sauvegarder l'image directement. Upload (img-iMfLB2YJ-1611275604649)(/img/bVcMQdS)]

D) Vient maintenant la partie intéressante : la file d'attente des tâches (microtâches) a une plus grande taille. priorité que la file d’attente des tâches (macrotâches). La boucle d'événements prend le rappel de promesse resolve() de la file d'attente des tâches et le place sur la pile d'appels. Ensuite, la pile d'appels exécute le rappel de promesse resolve() :

[Le transfert de l'image du lien externe a échoué. Le site source peut avoir un mécanisme anti-sangsue. Il est recommandé de sauvegarder l'image et de la télécharger directement (. img-nnqfgoo1-1611275604650)(/img /bVcMQey)]

E) Enfin, la boucle d'événements retire le rappel du minuteur timeout() de la file d'attente des tâches vers la pile d'appels. Ensuite, la pile d'appels exécute le rappel du minuteur timeout() :

[Le transfert de l'image du lien externe a échoué. Le site source peut avoir un mécanisme anti-sangsue. Il est recommandé de sauvegarder l'image et de la télécharger directement (. img-Fj54WaI0-1611275604650)(/ img/bVcMQeB)]

La pile d'appels est vide et l'exécution du script est terminée.

Résumé

Pourquoi les promesses immédiatement résolues sont-elles traitées plus rapidement que les minuteurs d'exécution immédiate ?

En raison des priorités des boucles d'événements, la file d'attente des tâches (qui stocke les rappels setTimeout() implémentés) a une priorité plus élevée que la file d'attente des tâches (qui stocke les rappels Promise expirés).

Adresse originale : https://dmitripavlutin.com/javascript-promises-settimeout/

Auteur : Milos Protic

Adresse de traduction : https://segmentfault .com/a/1190000038769853

Pour plus de connaissances liées à la programmation informatique, veuillez visiter : Vidéo de programmation ! !

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer