Maison >interface Web >js tutoriel >Explication détaillée du mécanisme de boucle d'événements dans nodejs
Cet article vous guidera à travers le mécanisme de boucle d'événements dans node. 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.
Le développement front-end est indissociable de JavaScript. JavaScript est un langage front-end Web principalement utilisé dans le développement Web et analysé et exécuté par le navigateur. Le rôle de js ne se limite pas seulement au développement front-end, il peut également être utilisé pour le développement côté serveur - nodejs. En tant que personne front-end avec des idéaux et des ambitions, si vous souhaitez élargir vos horizons et maîtriser un langage de développement côté serveur, nodejs est un très bon choix.
Recommandations associées : "Tutoriel nodejs "
Parce que vous maîtrisez la méthode de développement js, il est facile de démarrer avec node, ainsi que l'outil de gestion de packages npm améliore considérablement l'expérience de développement. Nodejs est célèbre pour sa méthode de travail d'E/S asynchrone non bloquante, et son mécanisme de traitement est appelé boucle d'événements.
Comprendre le mécanisme de boucle d'événements du nœud permet de mieux comprendre la méthode de traitement des événements du nœud et le calendrier d'exécution des événements asynchrones. Cet article explique principalement le mécanisme de boucle d'événements de nodejs, jetant les bases de l'apprentissage ultérieur du nœud.
Comme mentionné précédemment, Javascript est un langage frontal Web, principalement utilisé dans le développement Web, et est analysé et exécuté par le navigateur. , tandis que node .js est un environnement d'exécution JavaScript basé sur le moteur Chrome V8. Par conséquent, nodejs n'est pas un langage, une bibliothèque ou un framework, mais un environnement d'exécution js. En termes simples, le nœud peut analyser et exécuter du code js. Dans le passé, seuls les navigateurs pouvaient analyser et exécuter JS, mais désormais, Node peut faire fonctionner JS complètement sans le navigateur.
Il existe de nombreuses différences entre node.js et le navigateur js. Par exemple, js dans le navigateur inclut ecmascript, BOM et DOM, mais js dans nodejs n'a pas de BOM, DOM et uniquement emcscript. Et l'environnement d'exécution js de node fournit des API d'opération au niveau du serveur pour js, telles que : la lecture et l'écriture de fichiers, la construction de services réseau, la communication réseau, le serveur http, etc. La plupart de ces API sont regroupées dans des modules de base. De plus, le mécanisme de boucle d'événements du nœud est différent du mécanisme de boucle d'événements du navigateur js.
Tout le monde est déjà très clair sur la boucle d'événements js dans le navigateur À des fins de comparaison, je la mentionnerai brièvement ici.
Lorsque js est exécuté, les tâches synchrones et asynchrones entrent respectivement dans différents environnements d'exécution. Les tâches synchrones entrent dans le thread principal, c'est-à-dire la pile d'exécution principale, et les tâches asynchrones (requêtes ajax, settimeout, setinterval, poromise.resolve(), etc.) entrez dans la file d’attente des tâches. Différentes tâches asynchrones seront poussées dans différentes files d'attente de tâches, telles que les requêtes ajax, settimeout, setinterval, etc. Ces tâches seront poussées dans la file d'attente des tâches macro (Macro Task), tandis que la fonction Promise sera poussée dans la file d'attente des micro-tâches ( Microtâche). Le processus global de la boucle d'événements est le suivant :
Lorsque le code synchrone est exécuté, la pile d'exécution principale devient vide et les préparatifs commencent pour exécuter des tâches asynchrones.
Le thread principal vérifiera si la file d'attente des microtâches est vide. Si elle n'est pas vide, il parcourra toutes les microtâches de la file d'attente pour les exécuter, effacera la file d'attente des microtâches, puis vérifiez la file d’attente des tâches de macro. Si la file d'attente des microtâches est vide, passez directement à l'étape suivante.
Le thread principal parcourt la file d'attente des tâches macro et exécute la première tâche macro dans la file d'attente des tâches macro. S'il rencontre une tâche macro ou une micro-tâche pendant l'exécution, il continuera à traiter. Placez-le dans la file d'attente des tâches correspondante. Chaque fois qu'une macro-tâche est exécutée, la file d'attente des micro-tâches doit être parcourue et effacée
Effectuer les opérations de rendu et mettre à jour la vue
Démarrez la boucle d'événements suivante et répétez les étapes ci-dessus jusqu'à ce que les deux files d'attente de tâches soient effacées
Afin d'approfondir l'impact, prenons un petit exemple et regardez le code suivant Ce qui sera généré :
var le=Promise.resolve(2); console.log(le) console.log('3') Promise.resolve().then(()=>{ console.log('Promise1') setTimeout(()=>{ console.log('setTimeout2') },0) }) setTimeout(()=>{ console.log('setTimeout1') Promise.resolve().then(()=>{ console.log('Promise2') }) },0);
Utilisez le processus de boucle d'événements ci-dessus pour analyser :
六个阶段分别是:
事件循环中,每当进入某一个阶段,都会从该阶段对应的回调队列中取出函数去执行。当队列为空或者执行的回调函数数量到达系统设定的阈值,该阶段就会终止,然后检查NextTick队列和微任务队列,将其清空,之后进入下一个阶段。
这里面比较关键的是poll阶段:
同样的举个大大的,看看以下代码会输出什么:
console.log('start') setTimeout(() => { console.log('timer1') Promise.resolve().then(function() { console.log('promise1') }) }, 0) setTimeout(() => { console.log('timer2') Promise.resolve().then(function() { console.log('promise2') }) }, 0) Promise.resolve().then(function() { console.log('promise3') }) console.log('end')
利用node事件循环分析呗:
因此输出顺序是:start,end,promise3,timer1,promise1,timer2,promise2,如果能正确回答出来说明对node的循环机制有了大体的了解,实际node输出结果确实是这样:
那如下代码会输出什么呢?
process.nextTick(function(){ console.log(7); }); new Promise(function(resolve){ console.log(3); resolve(); console.log(4); }).then(function(){ console.log(5); }); process.nextTick(function(){ console.log(8); });
继续分析:
因此最终输出是:3,4,7,8,5,需要记住,process.nextTick 永远大于 promise.then的优先级
还有一个大家很容易混淆的点就是setTimout和setImmediate的执行时机,根据上面描述的node事件循环机制,setImmediate()应该在check阶段执行 与 而setTimeout在timer阶段执行,理论上setTimout比setImmediate先执行,看下面的代码:
setTimeout(() => console.log(1),0); setImmediate(() => console.log(2));
执行结果是什么?1,2 还是 2,1,其实都有可能,看实际node运行的结果:
可以看到两次执行的结果不一样,为什么呢?原因在于即使setTimeout的第二个参数默认为0,但实际上,Node做不到0秒就执行其回调,最少也要4毫秒。那么进入事件循环后,如果没到4毫秒,那么timers阶段就会被跳过,从而进入check阶段执行setImmediate回调,此时输出结果是:2,1;
如果进入事件循环后,超过4毫秒(只是个大概,具体值并不确定),setTimeout的回调会出现在timer阶段的队列里,回调将被执行,之后再进入poll阶段和check阶段,此时输出结果是:1,2
那如果两者在I/O周期内调用,谁先执行呢?看一下代码:
const fs = require('fs') fs.readFile('./test.txt', 'utf8' , (err, data) => { if (err) { console.error(err) return } setTimeout(() => { console.log('timeout'); }, 0); setImmediate(() => { console.log('immediate'); }); })
实际上,node中输出的结果总是immediate先输出,timeout后输出。因为I/O回调是在poll阶段执行,当回调执行完毕之后队列为空,发现存在setImmediate的回调就会进入check阶段,执行完毕后,再进入timer阶段。
本文结合代码示例,对node的事件循环机制做了比较详细描述。通过这篇文章,应该可以了解浏览器的事件循环机制是怎样的,node的循环机制是怎样的,以及nextTick和micro队列的优先级,setTimout和setImmediate执行时机等一些容易混淆的知识点。文章中不足和不对之处,欢迎在评论区交流讨论,一起探索,谢谢。
更多编程相关知识,请访问:编程入门!!
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!