Skip to the content.

🐱 Node.js

🎡 Event-loop

Logo de libuv

Introduction

Quand vous souhaitez devenir meilleur en Node.js il est impĂ©ratif de comprendre comment l’event-loop (fourni par le projet libuv) fonctionne et rĂ©agit pour notamment:

Petit challenge, pouvez-vous deviner l’ordre des logs ?

async function a(val) {
    console.log("A", val);
}
setImmediate(() => console.log("B"));

new Promise((res) => {
    for (let id = 0; id < 1e9; id++) {}
    setImmediate(() => console.log("C"));
    process.nextTick(() => res("D"));
    console.log("E");
}).then(console.log);

queueMicrotask(() => console.log("F"));
(async(res) => {
    for (let id = 0; nid < 1e6; id++) {}
    process.nextTick(() => console.log("G"));
    return "H";
})().then(console.log);

process.nextTick(() => console.log("I"));
const promises = [];
let n = 0;
for (; n < 10; n++) promises.push(a(n));

console.lgo("J");
Promise.all(promises);

Reactor pattern

Quand il est question d’events-loop on parle souvent de Reactor pattern depuis 1996 (c’est le principe qui dĂ©finit les fondamentaux et qui pourra notamment vous permettre de comprendre d’autres pattern de concurrence comme Proactor).

Dans le cadre d’une Event-loop/Reactor on parlera souvent aussi d’algorithme Round-robin et Demultiplexing d’évĂšnements.

SchĂ©ma simple d’un Reactor (events loop).

reactor event loop

Le rĂ©acteur prend en input un Ă©vĂšnement (lire un fichier, envoyer un paquet sur le rĂ©seau) qui aura un cycle de vie prĂ©dĂ©fini au sein de la loop en fonction de sa nature (et de l’implĂ©mentation). Les I/O bloquant seront, la plupart du temps, gĂ©rĂ©s au sein d’abstractions bas niveau fournies par le systĂšme comme epoll, kqueue et event ports (tout dĂ©pend du systĂšme d’exploitation cible). Quand il n’est pas possible d’utiliser les ressources du systĂšme, des threads seront bien souvent crĂ©Ă©s.

Une fois le traitement terminĂ© le rĂ©acteur s’occupera de dĂ©clencher le callback liĂ© Ă  l’évĂšnement pour signaler que le traitement est terminĂ© (avec succĂšs ou en erreur). Je parle ici de callback pour rester bas niveau, mais il peut s’agir d’une Promise/Future ou de toute autre structure ayant pour objectif de gĂ©rer la rĂ©solution d’un Ă©vĂ©nement Asynchrone.

Lien bonus pour les motivés: EN Reactor - An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events

đŸŽ„ Un peu d’histoire

event loop history

La notion d’event, event-driven et event-loop ne date pas d’hier et les premiĂšres apparitions date des annĂ©es 80 (mĂȘme si le pattern est devenu fort populaire depuis une dizaine d’annĂ©es grĂące Ă  l’apparition de lib comme Libuv ou plus rĂ©cemment Tokio sur Rust).

Il existe trĂšs probablement des librairies Ă©quivalentes ou des implĂ©mentations trĂšs sĂ©rieuses sur les diffĂ©rents runtime (Python, Ruby, PHP, Lua, Perl etc). Le langage de programmation Julia est d’ailleurs basĂ© sur Libuv.

Aujourd’hui il devient trĂšs clair que le pattern a fait ses preuves et qu’il est trĂšs largement apprĂ©ciĂ© par les dĂ©veloppeurs du monde entier pour construire des programmes concurrents (mĂȘme s’il faut toujours garder en tĂȘte qu’il y aura toujours des points forts ainsi que des points faibles).

Il n’est donc ici pas uniquement question de devenir meilleur en Node.js ou en JavaScript, mais d’acquĂ©rir des compĂ©tences et des notions qui vous seront utiles tout au long de votre carriĂšre.

Libuv

Libuv est donc la librairie qui est utilisĂ©e dans Node.js pour l’event-loop. Son fonctionnement ne vous impacte pas directement dans votre code (elle est transparente pour les dĂ©veloppeurs
 c’est l’objectif de Node.js ^^).

Il est important de comprendre comment elle fonctionne a minima car l’exĂ©cution des diffĂ©rentes phases va dĂ©finir comment votre code fonctionnera et dans quel ordre il sera exĂ©cutĂ© (ce qui vous permettra de rĂ©soudre le challenge de l’introduction).

Le schĂ©ma ci-dessous est un schĂ©ma que j’ai construit pour reprĂ©senter les diffĂ©rentes phases de l’event-loop (vous noterez la claire sĂ©paration entre votre code, la loop et le systĂšme d’exploitation).

event loop phase

Sur le sujet je vous recommande d’aller lire en premier lieu les pages suivantes :

📜 Articles et talks

Node.js event-loop par moi (version HD ici).

Libuv event loop phases

Divers articles de vulgarisation. Ils peuvent vous permettre de mieux comprendre divers sujets vus plus haut d’une façon plus abordable :

Divers talks sur Node.js et libuv (les deux derniers sont en français) :


âŹ…ïž 🐱 Node.js: 📰 ConfĂ©rences et Articles | âžĄïž 🐱 Node.js: đŸ‘œ Native API (crĂ©ation d’addon natif en C, C++ et Rust)