


Une analyse approfondie de la file d'attente des microtâches dans la boucle d'événements Node
Dans article précédent, nous avons appris que la boucle d'événements est un élément clé de Node.js, utilisé pour coordonner l'exécution de code synchrone et asynchrone.
Il se compose de six files d'attente différentes. Une file d'attente nextTick et une file d'attente Promise (appelée file d'attente de microtâches), une file d'attente de minuterie, une file d'attente d'E/S, une file d'attente de vérification et enfin la file d'attente d'arrêt. [Tutoriels associés recommandés : Tutoriel vidéo Nodejs, Enseignement de la programmation]
Dans chaque boucle, la fonction de rappel sera retirée de la file d'attente le cas échéant et exécutée sur la pile d'appels. À partir de cet article, nous allons effectuer quelques expériences pour nous assurer que notre compréhension de la boucle d'événements est correcte.
Notre première série d'expériences se concentrera sur la file d'attente nextTick et la file d'attente Promise. Mais avant de nous lancer dans l’expérience, nous devons comprendre comment mettre en file d’attente les fonctions de rappel.
Remarque : toutes les expériences ont été menées en utilisant le format de module CommonJS.
Fonction de rappel Enqueue
Pour ajouter la fonction de rappel à la file d'attente nextTick, nous pouvons utiliser la méthode intégrée process.nextTick()
. La syntaxe est très simple : process.nextTick(callbackFn)
. Lorsque la méthode est exécutée sur la pile d'appels, la fonction de rappel sera ajoutée à la file d'attente nextTick. process.nextTick()
方法。语法很简单:process.nextTick(callbackFn)
。当该方法在调用栈上执行时,回调函数将被加入到 nextTick 队列中。
要将回调函数加入到 Promise 队列中,我们需要使用 Promise.resolve().then(callbackFn)
。当 Promise 解决时(resolve),传递给 then()
的回调函数将被入队到 Promise 队列中。
现在我们已经了解了如何向两个队列添加回调函数,让我们开始第一个实验吧。
实验一
代码
// index.js console.log("console.log 1"); process.nextTick(() => console.log("this is process.nextTick 1")); console.log("console.log 2");
这段代码,记录了三个不同的语句。第二个语句使用 process.nextTick()
将回调函数排入 nextTick 队列。
可视化
第一个 console.log()
语句被推入调用栈中执行。它在控制台中记录相应的消息,然后弹出堆栈。
接下来,在调用栈上执行 process.nextTick()
,将回调函数入队到 nextTick 队列,并弹出。此时仍有用户编写的代码需要执行,因此回调函数必须等待其轮到。
执行继续进行,最后一个 console.log()
语句被推入堆栈中,该消息记录在控制台中,并将该函数从调用栈中弹出。现在,没有更多的用户编写同步代码需要执行,因此控制权进入事件循环。
nextTick 队列中的回调函数被推入调用栈,console.log()
被推入调用栈并且执行,在控制台记录相应的消息。
console.log 1 console.log 2 this is process.nextTick 1
推论
所有用户编写的同步 JavaScript 代码优先于异步代码执行。
让我们继续进行第二个实验。
实验二
代码
// index.js Promise.resolve().then(() => console.log("this is Promise.resolve 1")); process.nextTick(() => console.log("this is process.nextTick 1"));
我们有一个 Promise.resolve().then() 调用和一个 process.nextTick() 调用。
可视化
当调用栈执行第 1 行时,它将回调函数排队到 Promise 队列中;当调用栈执行第 2 行时,它将回调函数排队到 nextTick 队列中。
第 2 行后没有代码需要执行。
控制权进入事件循环,在其中 nextTick 队列优先于 Promise 队列(这是 Node.js 运行时的工作方式)。
事件循环执行 nextTick 队列回调函数,然后再执行 Promise 队列回调函数。
控制台显示“this is process.nextTick 1”,然后是“this is Promise.resolve 1”。
this is process.nextTick 1 this is Promise.resolve 1
推论
nextTick 队列中的所有回调函数优先于 Promise 队列中的回调函数执行。
让我带你走一遍上述第二个实验的更详细版本。
福利实验
代码
// index.js process.nextTick(() => console.log("this is process.nextTick 1")); process.nextTick(() => { console.log("this is process.nextTick 2"); process.nextTick(() => console.log("this is the inner next tick inside next tick") ); }); process.nextTick(() => console.log("this is process.nextTick 3")); Promise.resolve().then(() => console.log("this is Promise.resolve 1")); Promise.resolve().then(() => { console.log("this is Promise.resolve 2"); process.nextTick(() => console.log("this is the inner next tick inside Promise then block") ); }); Promise.resolve().then(() => console.log("this is Promise.resolve 3"));
该代码包含三个 process.nextTick()
调用和三个 Promise.resolve()
Promise.resolve().then(callbackFn)
. Lorsqu'une promesse est résolue, la fonction de rappel passée à then()
sera mise en file d'attente dans la file d'attente des promesses. 🎜🎜Maintenant que nous savons comment ajouter des fonctions de rappel à deux files d'attente, commençons notre première expérience. 🎜Expérience 1🎜Code
this is process.nextTick 1
this is process.nextTick 2
this is process.nextTick 3
this is the inner next tick inside next tick
this is Promise.resolve 1
this is Promise.resolve 2
this is Promise.resolve 3
this is the inner next tick inside Promise then block
Copier après la connexionCopier après la connexion🎜Ce code enregistre trois déclarations différentes. La deuxième instruction utilise process.nextTick()
pour mettre la fonction de rappel en file d'attente dans la file d'attente nextTick. 🎜Visualisation
🎜
🎜🎜premierconsole.log Le ( )
est poussée dans la pile d'appels pour exécution. Il enregistre le message approprié dans la console, puis affiche la pile. 🎜🎜Ensuite, exécutez process.nextTick()
sur la pile d'appels, mettez la fonction de rappel en file d'attente dans la file d'attente nextTick et affichez-la. Il reste encore du code écrit par l'utilisateur qui doit être exécuté à ce stade, la fonction de rappel doit donc attendre son tour. 🎜🎜L'exécution continue, la dernière instruction console.log()
est poussée sur la pile, le message est enregistré dans la console et la fonction est retirée de la pile d'appels. Désormais, il n’y a plus de code synchrone écrit par l’utilisateur à exécuter, le contrôle passe donc dans la boucle d’événements. 🎜🎜La fonction de rappel dans la file d'attente nextTick est poussée dans la pile d'appels, console.log()
est poussée dans la pile d'appels et exécutée, et le message correspondant est enregistré dans la console. 🎜rrreeeCorollaire
🎜Tout le code JavaScript synchrone écrit par l'utilisateur s'exécute avant le code asynchrone. 🎜
🎜Passons à la deuxième expérience. 🎜Expérience 2🎜Code
rrreee🎜Nous avons une Promise.resolve() Appel .then() et un appel process.nextTick(). 🎜Visualisation
🎜
🎜🎜Lorsque la pile d'appels est exécutée Sur la ligne 1, il met la fonction de rappel en file d'attente dans la file d'attente Promise lorsque l'appel est empilé ; exécute les 2 lignes, il met la fonction de rappel en file d'attente dans la file d'attente nextTick. 🎜🎜Aucun code ne doit être exécuté après la ligne 2. 🎜🎜Control entre dans la boucle d'événements, où la file d'attente nextTick a priorité sur la file d'attente Promise (c'est ainsi que fonctionne le runtime Node.js). 🎜🎜La boucle d'événements exécute la fonction de rappel de file d'attente nextTick, puis exécute la fonction de rappel de file d'attente Promise. 🎜🎜La console affiche " ceci est process.nextTick 1 ", puis " ceci est Promise.resolve 1 ". 🎜rrreeeCorollaire
🎜Toutes les fonctions de rappel de la file d'attente nextTick sont exécutées avant les fonctions de rappel de la file d'attente Promise. 🎜
🎜Laissez-moi vous expliquer une version plus détaillée de la deuxième expérience ci-dessus. 🎜Expérience de bien-être🎜Code
rrreee🎜Le Le code contient trois appels process.nextTick()
et trois instructions d'appel Promise.resolve()
. Chaque fonction de rappel enregistre le message approprié. 🎜
this is process.nextTick 1 this is process.nextTick 2 this is process.nextTick 3 this is the inner next tick inside next tick this is Promise.resolve 1 this is Promise.resolve 2 this is Promise.resolve 3 this is the inner next tick inside Promise then block
Code
rrreee🎜Nous avons une Promise.resolve() Appel .then() et un appel process.nextTick(). 🎜Visualisation
🎜
Corollaire
🎜Toutes les fonctions de rappel de la file d'attente nextTick sont exécutées avant les fonctions de rappel de la file d'attente Promise. 🎜🎜Laissez-moi vous expliquer une version plus détaillée de la deuxième expérience ci-dessus. 🎜
Expérience de bien-être🎜Code
rrreee🎜Le Le code contient trois appels process.nextTick()
et trois instructions d'appel Promise.resolve()
. Chaque fonction de rappel enregistre le message approprié. 🎜
但是,第二个 process.nextTick()
和第二个 Promise.resolve()
都有一个额外的 process.nextTick()
语句,每个都带有一个回调函数。
可视化
为了加快对此可视化的解释,我将省略调用栈讲解。当调用栈执行所有 6 个语句时,nextTick 队列中有 3 个回调函数,Promise 队列中也有 3 个回调函数。没有其他要执行的内容后,控制权进入事件循环。
我们知道,nextTick 队列中具有高优先级。首先执行第 1 个回调函数,并将相应的消息记录到控制台中。
接下来,执行第 2 个回调函数,记录了第 2 条日志语句。但是,这个回调函数包含另一个对 process.nextTick()
的调用,该方法内的回调函数(译注:即() => console.log("this is the inner next tick inside next tick")
)入队到nextTick 队列末尾。
然后 Node.js 执行第 3 个回调函数并将相应消息记录到控制台上。最初只有 3 个回调,但是因为第 2 次时向nextTick 队列又添加了一个,所以变成 4 个了。
事件循环将第 4 个回调函数推入调用栈,执行 console.log()
语句。
接着处理完 nextTick 队列之后,控制流程进入到 Promise 队列。Promise 队列与 nextTick 队列处理方式类似。
首先记录“Promise.resolve 1”,然后是“Promise.resolve 2”,这时因为调用 process.nextTick() 的原因,一个函数(译注:即 () => console.log("this is the inner next tick inside Promise then block")
) 被推入 nextTick 队列了。尽管如此,控制流程仍停留在 Promise 队列,因此还会继续执行队列中的其他函数。然后我们得到“Promise.resolve 3”,此时 Promise 队列为空。
Node.js 将再次检查微任务队列中是否有新的回调。由于 nextTick 队列中有一个回调,因此会执行这个回调,导致我们的最后一条日志输出。
this is process.nextTick 1 this is process.nextTick 2 this is process.nextTick 3 this is the inner next tick inside next tick this is Promise.resolve 1 this is Promise.resolve 2 this is Promise.resolve 3 this is the inner next tick inside Promise then block
这可能是一个稍微高级的实验,但推论仍然相同。
推论
nextTick 队列中的所有回调函数优先于 Promise 队列中的回调函数执行。
使用 process.nextTick()
时要小心。过度使用此方法可能会导致事件循环饥饿,从而阻止队列中的其余部分运行。当存在大量的 nextTick() 调用时,I/O 队列是无法执行自己的回调函数的。官方文档建议使用 process.nextTick()
的两个主要场景:处理错误或在调用栈为空事件循环继续之前执行回调用。所以在使用 process.nextTick()
时,要明智一些。
总结
实验表明,用户编写的所有同步 JavaScript 代码优先于异步代码执行,并且 nextTick 队列中的所有回调函数优先于 Promise 队列中的回调函数执行。
原文链接:Visualizing nextTick and Promise Queues in Node.js Event Loop,2023年3月30日,by Vishwas Gopinath
更多node相关知识,请访问:nodejs 教程!
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)

PHP et Vue : une combinaison parfaite d'outils de développement front-end À l'ère actuelle de développement rapide d'Internet, le développement front-end est devenu de plus en plus important. Alors que les utilisateurs ont des exigences de plus en plus élevées en matière d’expérience des sites Web et des applications, les développeurs front-end doivent utiliser des outils plus efficaces et plus flexibles pour créer des interfaces réactives et interactives. En tant que deux technologies importantes dans le domaine du développement front-end, PHP et Vue.js peuvent être considérés comme une arme parfaite lorsqu'ils sont associés. Cet article explorera la combinaison de PHP et Vue, ainsi que des exemples de code détaillés pour aider les lecteurs à mieux comprendre et appliquer ces deux éléments.

Lors des entretiens de développement front-end, les questions courantes couvrent un large éventail de sujets, notamment les bases HTML/CSS, les bases JavaScript, les frameworks et les bibliothèques, l'expérience du projet, les algorithmes et les structures de données, l'optimisation des performances, les requêtes inter-domaines, l'ingénierie front-end, les modèles de conception et les nouvelles technologies et tendances. Les questions de l'intervieweur sont conçues pour évaluer les compétences techniques du candidat, son expérience en matière de projet et sa compréhension des tendances du secteur. Par conséquent, les candidats doivent être parfaitement préparés dans ces domaines pour démontrer leurs capacités et leur expertise.

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

Django est un framework d'application Web écrit en Python qui met l'accent sur un développement rapide et des méthodes propres. Bien que Django soit un framework Web, pour répondre à la question de savoir si Django est un front-end ou un back-end, vous devez avoir une compréhension approfondie des concepts de front-end et de back-end. Le front-end fait référence à l'interface avec laquelle les utilisateurs interagissent directement, et le back-end fait référence aux programmes côté serveur. Ils interagissent avec les données via le protocole HTTP. Lorsque le front-end et le back-end sont séparés, les programmes front-end et back-end peuvent être développés indépendamment pour mettre en œuvre respectivement la logique métier et les effets interactifs, ainsi que l'échange de données.

En tant que langage de programmation rapide et efficace, le langage Go est très populaire dans le domaine du développement back-end. Cependant, peu de gens associent le langage Go au développement front-end. En fait, l’utilisation du langage Go pour le développement front-end peut non seulement améliorer l’efficacité, mais également ouvrir de nouveaux horizons aux développeurs. Cet article explorera la possibilité d'utiliser le langage Go pour le développement front-end et fournira des exemples de code spécifiques pour aider les lecteurs à mieux comprendre ce domaine. Dans le développement front-end traditionnel, JavaScript, HTML et CSS sont souvent utilisés pour créer des interfaces utilisateur.

Django : Un framework magique capable de gérer à la fois le développement front-end et back-end ! Django est un framework d'application Web efficace et évolutif. Il est capable de prendre en charge plusieurs modèles de développement Web, notamment MVC et MTV, et peut facilement développer des applications Web de haute qualité. Django prend non seulement en charge le développement back-end, mais peut également créer rapidement des interfaces frontales et obtenir un affichage de vue flexible via un langage de modèle. Django combine le développement front-end et le développement back-end dans une intégration transparente, afin que les développeurs n'aient pas à se spécialiser dans l'apprentissage.

Combinaison de Golang et de la technologie front-end : pour explorer le rôle de Golang dans le domaine front-end, des exemples de code spécifiques sont nécessaires. Avec le développement rapide d'Internet et des applications mobiles, la technologie front-end est devenue de plus en plus importante. Dans ce domaine, Golang, en tant que puissant langage de programmation back-end, peut également jouer un rôle important. Cet article explorera comment Golang est combiné avec la technologie front-end et démontrera son potentiel dans le domaine front-end à travers des exemples de code spécifiques. Le rôle de Golang dans le domaine front-end est celui d'un outil efficace, concis et facile à apprendre.

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
