Explication détaillée d'exemples de boucles d'événements js
J'ai déjà lu quelques blogs sur les boucles d'événements, mais après ne pas les avoir lus pendant un moment, j'ai réalisé que je les avais tous oubliés, alors j'ai décidé d'écrire un blog pour les résumer !
Tout d'abord, expliquons ce qu'est la boucle d'événements :
Pour autant que nous le sachions, le js du navigateur est monothread, c'est-à-dire disons, au plus un seul segment de code s'exécute en même temps, mais le navigateur peut très bien gérer les requêtes asynchrones, alors pourquoi ? Regardons d'abord une image
À partir de l'image ci-dessus, nous pouvons voir que le thread principal js a une pile d'exécution et que tout le code js s'exécutera dans la pile d'exécution. Lors de l'exécution du code, si vous rencontrez du code asynchrone (tel que setTimeout, ajax, promise.then et les clics de l'utilisateur, etc.), alors le navigateur mettra ces codes dans un thread (ici nous l'appelons un derrière-le -scenes thread) L'attente ne bloque pas l'exécution du thread principal. Le thread principal continue d'exécuter le code restant dans la pile lorsque le code du thread d'arrière-plan est prêt (par exemple, le délai setTimeout est écoulé et la requête ajax. reçoit une réponse), le thread le traitera. La fonction de rappel est placée dans la file d'attente des tâches en attente d'exécution. Lorsque le thread principal aura fini d'exécuter tout le code de la pile, il vérifiera s'il y a une tâche à exécuter dans la File d'attente des tâches S'il y a une tâche à exécuter, alors la tâche sera mise. dans la pile d'exécution pour l'exécution. Si la file d'attente des tâches actuelle est vide, elle continuera d'attendre en boucle que la tâche arrive. C’est ce qu’on appelle une boucle d’événements.
Alors, voici la question. S’il y a de nombreuses tâches dans la file d’attente des tâches, laquelle doit être exécutée en premier ?
En fait (comme le montre l'image ci-dessus), js a deux files d'attente de tâches, l'une s'appelle Macrotask Queue (Task Queue) et l'autre s'appelle Microtask Queue
Le premier est principalement utilisé pour effectuer des travaux à relativement grande échelle, les plus courants incluent setTimeout, setInterval, les opérations d'interaction utilisateur, le rendu de l'interface utilisateur, etc.
Le second est principalement utilisé pour effectuer des travaux à relativement petite échelle, ce qui est courant. Il existe Promise, process.nextTick (nodejs)
Alors, quelles sont les différences spécifiques entre les deux ? , si deux tâches apparaissent en même temps, laquelle faut-il choisir ?
En fait, ce que fait la boucle d'événements est la suivante :
Vérifier si la file d'attente des macrotâches est vide . Sinon, passez à l'étape suivante. Si elle est vide, passez à 3
Prendre la tâche en tête de file d'attente (avec le temps d'attente le plus long) depuis la liste. File d'attente Macrotask et exécutez-la dans la pile d'exécution (une seule). Après l'exécution, passez à l'étape suivante
Vérifiez si la file d'attente Microtask est vide, sinon passez à l'étape suivante. , sinon, passez à 1 (démarrez une nouvelle boucle d'événements)
Obtenir de la file d'attente Microtask La tâche en tête de file d'attente (avec le temps le plus long dans la file d'attente) va dans la file d'attente des événements pour l'exécution. Après l'exécution, passe à 3
Parmi eux, la tâche de microtâche ajoutée lors de l'exécution du code sera dans la période actuelle de la boucle d'événement. , et la tâche de macrotâche nouvellement ajoutée ne peut attendre que la prochaine boucle d'événement pour s'exécuter (une boucle d'événement n'exécute qu'une seule macrotâche)
Tout d'abord, regardons un morceau de code
console.log(1) setTimeout(function() { //settimeout1 console.log(2) }, 0); const intervalId = setInterval(function() { //setinterval1 console.log(3) }, 0) setTimeout(function() { //settimeout2 console.log(10) new Promise(function(resolve) { //promise1 console.log(11) resolve() }) .then(function() { console.log(12) }) .then(function() { console.log(13) clearInterval(intervalId) }) }, 0); //promise2 Promise.resolve() .then(function() { console.log(7) }) .then(function() { console.log(8) }) console.log(9)
Que voulez-vous pensez-vous que le résultat devrait être ?
Les résultats que je génère dans l'environnement de nœud et la console Chrome sont les suivants :
1 9 7 8 2 3 10 11 12 13
Dans l'exemple ci-dessus
la première boucle d'événement :
console.log(1) est exécuté, sortie 1
settimeout1 est exécuté et ajouté à la file d'attente des macrotâches
setinterval1 est exécuté et ajouté à la file d'attente des macrotâches
settimeout2 est exécuté et ajouté à la file d'attente des macrotâches
promise2 est exécuté et ses deux La fonction then est ajoutée à la file d'attente des microtâches
console.log(9) est exécutée et la sortie est 9
-
Selon la définition de la boucle d'événements, new sera exécuté ensuite. Les tâches de microtâches ajoutées sont exécutées dans l'ordre d'entrée dans la file d'attente. Console.log(7) et console.log(8) sont affichés. sont affichés. La file d'attente des microtâches est vide. Revenez à la première étape et entrez dans la boucle d'événements suivante. À ce stade, la file d'attente des macrotâches est : settimeout1, setinterval1, settimeout2
- de la file d'attente des macrotâches Obtenez la tâche en tête de l'équipe (settimeout1) et exécutez-la Sortie 2
- La file d'attente des microtâches est. vide. Revenez à la première étape et entrez dans la boucle d'événements suivante. À ce stade, la file d'attente des macrotâches est : setinterval1, settimeout2
.
- Prenez la tâche à la tête de l'équipe (setinterval1) de la file d'attente des macrotâches et exécutez-la, sortie 3, puis ajoutez le setinterval1 nouvellement généré à la file d'attente des macrotâches
- Le La file d'attente des microtâches est vide, revenez à la première étape et entrez dans la boucle d'événements suivante. À ce moment, la file d'attente des macrotâches est : settimeout2, setinterval1
- Prenez la tâche à la tête de l'équipe (settimeout2) de la file d'attente des macrotâches et exécutez-la, sortie 10, et exécutez la fonction dans la nouvelle promesse (la fonction dans la nouvelle promesse est une opération synchrone, pas une opération asynchrone), sortie 11, et ajoute ses deux fonctions then à la file d'attente des microtâches
Depuis la file d'attente des microtâches, prenez la tâche en tête de file d'attente et exécutez-la jusqu'à ce qu'elle soit vide. Par conséquent, les deux tâches de microtâches nouvellement ajoutées sont exécutées en séquence, sorties 12 et 13, et setinterval1 est effacé
À ce moment, la file d'attente des microtâches et la file d'attente des macrotâches sont vides, et le navigateur vérifiera toujours si la file d'attente est vide et attends le nouveau. La tâche est ajoutée à la file d'attente.
Ici, vous vous demandez peut-être, dans la première boucle, pourquoi la macrotâche n'est-elle pas exécutée en premier ? Car selon le processus, ne devrions-nous pas d'abord vérifier si la file d'attente des macrotâches est vide, puis vérifier la file d'attente des microtâches ?
Raison : Parce que la tâche exécutée dans le thread principal js au début est la tâche de macrotâche, et selon le processus de la boucle d'événement, une seule tâche de macrotâche sera exécutée dans une boucle d'événement. Par conséquent, après l'exécution du code. du thread principal, il ira de Prenez la première tâche de la file d'attente des microtâches et exécutez-la.
Remarque :
Lors de l'exécution d'une tâche de microtâche, elle n'entrera dans la boucle d'événements suivante que lorsque la file d'attente des microtâches est vide. Par conséquent, si elle génère continuellement de nouvelles. Les tâches de microtâches entraîneront l'exécution de tâches de microtâches par le thread principal, et il n'y a aucun moyen d'exécuter des tâches de macrotâches. De cette façon, nous ne pourrons pas effectuer de rendu d'interface utilisateur/opérations d'E/S/requêtes ajax. Par conséquent, nous devrions éviter cette situation. . se produire. Dans process.nexttick dans nodejs, vous pouvez définir le nombre maximum d'appels pour éviter de bloquer le thread principal.
Avec cela, nous introduisons un nouveau problème, le problème de la minuterie. La minuterie est-elle réelle et fiable ? Par exemple, si j'exécute une commande : setTimeout(task, 100), sera-t-elle exécutée exactement après 100 millisecondes ? En fait, sur la base de la discussion ci-dessus, nous pouvons savoir que cela est impossible.
Je pense que tout le monde devrait connaître la raison, car après avoir exécuté setTimeout(task,100), vous vous assurez simplement que la tâche entrera dans la file d'attente des macrotâches après 100 millisecondes, mais cela ne signifie pas qu'elle peut s'exécuter immédiatement, peut-être Le thread principal effectue actuellement une opération fastidieuse, ou il peut y avoir de nombreuses tâches dans la file d'attente des microtâches, c'est peut-être la raison pour laquelle tout le monde a critiqué setTimeout
Ce qui précède n'est que mon point de vue personnel. de la boucle événementielle. Quelques avis et références d'autres excellents articles
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!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Tutoriel JavaScript : Comment obtenir le code d'état HTTP, des exemples de code spécifiques sont requis Préface : Dans le développement Web, l'interaction des données avec le serveur est souvent impliquée. Lors de la communication avec le serveur, nous devons souvent obtenir le code d'état HTTP renvoyé pour déterminer si l'opération a réussi et effectuer le traitement correspondant en fonction de différents codes d'état. Cet article vous apprendra comment utiliser JavaScript pour obtenir des codes d'état HTTP et fournira quelques exemples de codes pratiques. Utilisation de XMLHttpRequest

jQuery est une bibliothèque JavaScript populaire qui peut être utilisée pour simplifier la manipulation du DOM, la gestion des événements, les effets d'animation, etc. Dans le développement Web, nous rencontrons souvent des situations dans lesquelles nous devons modifier la liaison d'événements sur des éléments sélectionnés. Cet article explique comment utiliser jQuery pour lier des événements de modification d'éléments sélectionnés et fournit des exemples de code spécifiques. Tout d'abord, nous devons créer un menu déroulant avec des options utilisant des étiquettes :

L'expression Lambda sort de la boucle, des exemples de code spécifiques sont nécessaires en programmation, la structure de boucle est une syntaxe importante qui est souvent utilisée. Cependant, dans certaines circonstances, nous pouvons vouloir sortir de la boucle entière lorsqu'une certaine condition est remplie dans le corps de la boucle, plutôt que de simplement terminer l'itération en cours de la boucle. À l'heure actuelle, les caractéristiques des expressions lambda peuvent nous aider à atteindre l'objectif de sortir de la boucle. L'expression Lambda est un moyen de déclarer une fonction anonyme, qui peut définir une logique de fonction simple en interne. C'est différent d'une déclaration de fonction ordinaire,

Introduction à la méthode d'obtention du code d'état HTTP en JavaScript : Dans le développement front-end, nous devons souvent gérer l'interaction avec l'interface back-end, et le code d'état HTTP en est une partie très importante. Comprendre et obtenir les codes d'état HTTP nous aide à mieux gérer les données renvoyées par l'interface. Cet article explique comment utiliser JavaScript pour obtenir des codes d'état HTTP et fournit des exemples de code spécifiques. 1. Qu'est-ce que le code d'état HTTP ? Le code d'état HTTP signifie que lorsque le navigateur lance une requête au serveur, le service

Cet article expliquera en détail comment PHP renvoie toutes les valeurs d'un tableau pour former un tableau. L'éditeur pense que c'est assez pratique, je le partage donc avec vous comme référence. J'espère que vous pourrez gagner quelque chose après avoir lu cet article. . Utilisation de la fonction array_values() La fonction array_values() renvoie un tableau de toutes les valeurs d'un tableau. Il ne conserve pas les clés du tableau d'origine. $array=["foo"=>"bar","baz"=>"qux"];$values=array_values($array);//$values sera ["bar","qux"]Utilisation une boucle peut utiliser une boucle pour obtenir manuellement toutes les valeurs du tableau et les ajouter à un nouveau

Les méthodes de création d'applications basées sur des événements en PHP incluent l'utilisation d'EventSourceAPI pour créer une source d'événements et l'utilisation de l'objet EventSource pour écouter les événements côté client. Envoyez des événements à l'aide de Server Sent Events (SSE) et écoutez les événements côté client à l'aide d'un objet XMLHttpRequest. Un exemple pratique consiste à utiliser EventSource pour mettre à jour les inventaires en temps réel sur un site Web de commerce électronique. Ceci est réalisé côté serveur en modifiant l'inventaire de manière aléatoire et en envoyant des mises à jour, et le client écoute les mises à jour d'inventaire via EventSource et les affiche dans. temps réel.

Interface Iterator L'interface Iterator est une interface utilisée pour parcourir les collections. Il fournit plusieurs méthodes, notamment hasNext(), next() et remove(). La méthode hasNext() renvoie une valeur booléenne indiquant s'il existe un élément suivant dans la collection. La méthode next() renvoie l'élément suivant de la collection et le supprime de la collection. La méthode Remove() supprime l'élément actuel de la collection. L'exemple de code suivant montre comment utiliser l'interface Iterator pour parcourir une collection : Listnames=Arrays.asList("John","Mary","Bob");Iterator

Remplacement des appels récursifs dans les fonctions Java par itération En Java, la récursivité est un outil puissant utilisé pour résoudre divers problèmes. Cependant, dans certains cas, l’utilisation de l’itération peut s’avérer une meilleure option car elle est plus efficace et moins sujette aux débordements de pile. Voici les avantages de l'itération : Plus efficace puisqu'elle ne nécessite pas la création d'un nouveau stack frame à chaque appel récursif. Les débordements de pile sont moins susceptibles de se produire car l'utilisation de l'espace de pile est limitée. Méthodes itératives comme alternative aux appels récursifs : Il existe plusieurs méthodes en Java pour convertir des fonctions récursives en fonctions itératives. 1. Utiliser la pile L'utilisation de la pile est le moyen le plus simple de convertir une fonction récursive en fonction itérative. La pile est une structure de données dernier entré, premier sorti (LIFO), similaire à une pile d'appels de fonction. publicintfa
