Maison  >  Article  >  interface Web  >  Analyse de la boucle d'événements dans Node

Analyse de la boucle d'événements dans Node

不言
不言original
2018-07-20 10:30:001312parcourir

Cet article vous présente l'analyse de la 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.

Chaque étape de la boucle d'événements

Le processus de boucle d'événements de Node.js est à peu près le suivant :

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

Chaque étape a sa propre file d'attente de tâches. étape Une fois que toutes les files d'attente de tâches ont été exécutées ou que le nombre maximum de tâches exécutées a été atteint, il entrera dans l'étape suivante.

Phase des minuteries

Cette phase exécutera les tâches planifiées définies par setTimeout et setInterval.
Bien sûr, ce timing n'est pas précis, mais une fois le temps de timing dépassé, une fois l'opportunité d'exécution obtenue, elle sera exécutée immédiatement.

Étape de rappels en attente

Cette étape effectuera certaines opérations liées au système sous-jacent, telles que les erreurs renvoyées par les connexions TCP, etc. Lorsque ces erreurs surviennent, elles seront reportées par Node au cycle suivant.

Phase d'interrogation

Cette phase est utilisée pour exécuter des rappels liés aux opérations IO. Node demandera au système d'exploitation si un nouvel événement IO a été déclenché, puis exécutera le rappel correspondant. Presque toutes les opérations, à l'exception des événements programmés, setImmediate() et close callbacks seront exécutées dans cette phase.

phase de vérification

Cette phase exécutera les tâches définies par setImmediate().

phase de rappels de fermeture

Si un socket ou un handle(句柄) est fermé brutalement, par exemple via socket.destroy(), l'événement close sera émis dans cette phase.

Exécution spécifique de la boucle d'événements

Une fois la boucle d'événements initialisée, elle se déroulera selon le processus indiqué dans la figure ci-dessus :

  1. Tout d'abord, le minuteur sera exécuté en séquence Tâches et pending callback rappels

  2. puis entrera dans les étapes idle et prepare, où une certaine logique interne de Node sera exécutée ;

  3. Entrez ensuite dans la poll phase de sondage. À ce stade, tous les rappels IO seront exécutés, comme la lecture de fichiers, les opérations réseau, etc. L'étape poll a une file d'attente de tâches poll queue. Le processus d'exécution de cette étape est relativement long, comme suit :

  • Lors de l'entrée dans cette étape, il vérifiera d'abord si la file d'attente de synchronisation timeout a des tâches exécutables . Si tel est le cas, il passera à 定时器阶段 pour exécution.

  • S'il n'y a pas de 定时器任务, la file d'attente des tâches poll queue sera vérifiée. Si elle n'est pas vide, toutes les tâches seront parcourues et exécutées jusqu'à ce qu'elles soient toutes exécutées ou la. le nombre maximum de tâches pouvant être exécutées est atteint.

  • poll queue Une fois l'exécution de la file d'attente des tâches terminée, il vérifiera s'il y a des tâches dans la file d'attente des tâches setImmediate. Si tel est le cas, la boucle d'événements sera transférée au suivant <. 🎜> scène. check

  • S'il n'y a pas de tâche

    , alors Node attendra ici l'arrivée de nouveaux rappels IO et les exécutera immédiatement. setImmediate

Remarque : Cette attente ne continuera pas éternellement, mais après avoir atteint une limite, passez à l'étape suivante pour l'exécution.

et setTimeout()setImmediate()

Un petit secret

n'est en fait pas un secret, mais je viens de le découvrir après avoir vérifié les informations.

C'est-à-dire : dans Node,
sera converti en setTimeout(callback, 0) . setTimeout(callback, 1)Veuillez vous référer ici pour plus de détails. L'ordre d'exécution de

et setTimeout()setImmediate()

L'ordre d'exécution des deux tâches planifiées suivantes s'exécute de manière incohérente dans des circonstances différentes.

setTimeout(function() {
    console.log(&#39;timeout&#39;);
}, 0);

setImmediate(function() {
    console.log(&#39;immediate&#39;);
});
Régler le timer dans le code ordinaire

Si vous définissez ces deux tâches planifiées dans la phase d'exécution du code ordinaire (par exemple, dans le bloc de code le plus externe), leur ordre d'exécution n'est pas fixé.

  1. Tout d'abord, le

    que nous avons défini a été converti en setTimeout(callback, 0), donc en entrant dans l'étape setTimeout(callback, 1), il sera jugé en fonction de l'heure actuelle si le le timing a dépassé 定时器. 1ms

  2. Avant d'entrer dans la phase de minuterie, la boucle d'événements appellera une méthode pour mettre à jour l'heure actuelle par le système. Étant donné que d'autres programmes s'exécutent dans le système en même temps, le système en a besoin. pour attendre la fin des processus d'autres programmes. Obtenez l'heure précise, il peut donc y avoir un certain retard dans la mise à jour de l'heure.

  3. Lors de la mise à jour de l'heure, s'il n'y a pas de retard et que le temps est inférieur à

    , la tâche 1ms sera exécutée en premier s'il y a un retard et cette fois ; atteint la limite de immediate, 1ms La tâche sera exécutée en premier. timeout

Réglez le minuteur dans le rappel IO

Si nous définissons ces deux minuteurs dans le rappel IO, alors la tâche

sera exécutée en premier pour les raisons suivantes :setImmediate

  1. 进入 poll phase 轮询阶段之前会先检查是否有 timer 定时任务。

  2. 如果没有 timer 定时任务,才会执行后面的 IO 回调。

  3. 我们在 IO 回调中设置 setTimeout 定时任务,这时已经过了 timer 检查阶段,所以 timer 定时任务会被推迟到下一个循环中执行。

process.nextTick()

无论在事件循环的哪个阶段,只要使用 process.nextTick() 添加了回调任务,Node 都会在进入下一阶段之前把 nextTickQueue 队列中的任务执行完。

setTimeout(function() {
    setImmediate(() => {
        console.log('immediate');
    });
    process.nextTick(() => {
        console.log('nextTick');
    });
}, 0);
// nextTick
// immediate

上述代码中,总是先执行 nextTick 任务,就是因为在循环在进入下一个阶段之前会先执行 nextTickQueue 中的任务。下面代码的执行结果也符合预期。

setImmediate(() => {
    setTimeout(() => {
        console.log('timeout');
    }, 0);
    process.nextTick(() => {
        console.log('nextTick');
    });
});
// nextTick
// timeout

相关推荐:

关于Node异步 I/O的介绍

关于Node模块机制的解析

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn