Maison  >  Article  >  interface Web  >  Cet article vous amènera à comprendre l'eventloop dans Node.js

Cet article vous amènera à comprendre l'eventloop dans Node.js

青灯夜游
青灯夜游avant
2022-01-04 18:44:132311parcourir

Le thread principal lit les événements de la « file d'attente des tâches ». Ce processus est cyclique, donc l'ensemble du mécanisme de fonctionnement est également appelé Event Loop. L'article suivant vous aidera à maîtriser l'eventloop dans Node.js J'espère qu'il vous sera utile !

Cet article vous amènera à comprendre l'eventloop dans Node.js

En fait, j'ai aussi parlé de l'eventloop dans le navigateur dans l'article précédent. Cependant, la boucle d'événement dans NodeJs est différente de celle du navigateur. Maîtriser eventloop est une compétence très importante pour les personnes qui écrivent nodejs. Parce que cela signifie que vous pouvez non seulement écrire des js, mais aussi étudier des NodeJs.

Pourquoi y a-t-il une boucle événementielle ?

Nous savons que l'essence de NodeJs est de déplacer la v8 du navigateur pour qu'elle s'exécute dans le système d'exploitation, il apporte donc également la boucle d'événements du navigateur. Mais pourquoi un design comme eventloop apparaît-il ?

D'un point de vue historique, js a été conçu comme un langage très simple pour faire fonctionner dom sur la page (je crois que tout le monde a entendu l'histoire selon laquelle js a été conçu en seulement 10 jours). Pour cet objectif, nous espérons certainement que l’exécution de js sera aussi simple et légère que possible. Le moteur de rendu aussi léger que js s'exécute dans un thread.

Ensuite, le problème vient. Si vous exécutez js sur un thread, lorsque le code est linéaire, il n'y a bien sûr pas de problème. Mais sur la page, nous avons besoin des interactions des utilisateurs, et ces interactions ne savent pas pourquoi ni quand elles se produisent. Comment gérer js ? S'il y a du code en cours d'exécution devant vous, comment le programme doit-il réagir lorsqu'un utilisateur interagit ? Si l'interaction de l'utilisateur est traitée en premier, le programme d'origine sera suspendu (c'est-à-dire bloqué). Afin d'éviter ce type de blocage, js adopte une méthode qui consiste à utiliser une file d'attente de messages pour stocker ce type d'interaction utilisateur. Une fois l'exécution de tous les programmes terminée, accédez à la file d'attente des messages pour obtenir l'événement d'interaction, puis exécutez-le. Cela résout le problème de blocage.

Boucle d'événements du navigateur

Nous savons tous que lorsque le navigateur parcourt la page, une interaction de l'utilisateur peut se produire à tout moment, afin de répondre immédiatement à l'utilisateur. js ne sera pas fermé, il continuera à tourner en boucle. C'est à peu près le suivant :

向消息队列拿任务-->执行任务-->执行完毕--> 向消息队列拿任务--> ....

Bien sûr, nous avons mentionné dans l'article précédent sur la boucle d'événements que afin de classer les différentes tâches asynchrones, il existe en fait une distinction entre les macro-tâches et les micro-tâches dans la boucle d'événements. Leur exécution est à peu près similaire à celle du navigateur, mais nodeJs distingue différentes tâches de macro à différents moments. Voici l'organigramme officiel :

Vous pouvez voir que chaque boucle d'événement dans nodeJs est divisée en 6 périodes spécifiques, et chaque période utilise des tâches macro désignées. Ensuite, avant que les macro-tâches de chaque période ne soient exécutées, la file d'attente des micro-tâches sera exécutée en premier. "Aperçu" retour s

L'exécution est retardée jusqu'à la prochaine boucle itération Les rappels d'E/S

Cet article vous amènera à comprendre leventloop dans Node.js

idle, prepare

ne sont utilisés qu'en interne, les développeurs ne peuvent pas prêter attention à

pollExecutionsetImmediate( )fermer les rappelstels que socket.on('close', ...)
pour récupérer de nouveaux événements d'E/S ; rappels (Presque tous les rappels seront exécutés, à l'exception des rappels de fermeture et des rappels programmés par les minuteries et des rappels programmés par setImmediate(), qui seront bloqués à ce stade au moment approprié) check

其实通过上述表格,我们已经很清晰知道整个事件循环机制的执行顺序了。但可能大家还会有一些疑问。下面来详细讲一下。

pending callbacks

这个阶段其实是处理由于操作系统出错,导致一些本应在上次事件循环中执行的回调。例如一些TCP错误。因此这部分,开发者不能主动操作,是NodeJs的一些容错机制。

check

同样的,setImmediate是nodejs特有的api,他可以立即创建一个异步宏任务。不仅如此,nodejs在事件循环中还专门设了一个check时期,在这个时期会专门执行setImmediate的回调。甚至你可以在这个时期中如果不停的产生setImmediate回调,eventloop会优先处理。

close callbacks

这个时期处理关闭事件,如socket.on('close', ...) 等这样可以确保在一些通讯结束前,所有任务都完成了。

微任务在eventloop中

我们先来回顾浏览器与nodejs的差异:

宏任务:

任务 浏览器 Node
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame

微任务:

任务 浏览器 Node
process.nextTick
MutationObserver
Promise.then catch finally

可以看到process.nextTick是nodejs特有的微任务,不仅如此,process.nextTick()的优先级高于所有的微任务,每一次清空微任务列表的时候,都是先执行 process.nextTick()

执行差异

不仅是任务类型上有差异,在执行上2个环境其实也有差异。在浏览器上执行任务的时候,每执行一个宏任务之前,需要先确保微任务队列执行完了。而在nodejs上是每个时期之前,先确保微任务队列执行完。也就是说在假如在timer时期,会先把所有setTimeout,setInterval的宏任务执行完。在执行完微任务,再进入下个时期。

注意:以上执行规则是在nodejs的v11版本之前的规则。在11版本之后nodejs的执行输出是跟浏览器一样的。

setImmediate() vs setTimeout()

setImmediate() 和 setTimeout()的执行先后顺序是不一定的,就是说如果你不停地执行以下代码,每次得到的结果可能是不一样的。

setTimeout(() => {
  console.log('timeout');
}, 0);

setImmediate(() => {
  console.log('immediate');
});

其中的原因是程序对时间的处理是有误差的。在setTimeout方法中设置的时间,不一定是准确的。同时在回调触发时,也无法确认事件循环处在哪个时期,可能是timer,也可能是check。所有会有不同的结果。

总结

eventloop是js运行机制里的重点内容,对于NodeJs来说,eventloop的操作空间则更大。因为它被细分为不同的时期,从而让我们可能把逻辑进一步细化。同时利用nextTick的最高优先级,可以写出在浏览器无法实现的代码。因此对于深入NodeJs的开发者来说,eventloop往往是他们考察新人对NodeJs理解的第一步。

更多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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer