Els Worker Threads són una característica avançada de Node.js que permet executar codi JavaScript en fils paral·lels. Això és especialment útil per a tasques que requereixen molta CPU, ja que Node.js és tradicionalment de fil únic i pot tenir problemes de rendiment amb operacions intensives.

Conceptes Clau

  1. Fil Únic vs. Múltiples Fils:

    • Fil Únic: Node.js executa el codi JavaScript en un sol fil, utilitzant el bucle d'esdeveniments per gestionar operacions asíncrones.
    • Múltiples Fils: Amb els Worker Threads, podem crear fils addicionals per executar codi en paral·lel, millorant el rendiment per a tasques intensives.
  2. Mòdul worker_threads:

    • Aquest mòdul proporciona una API per crear i gestionar fils de treball (workers).
  3. Worker:

    • Un Worker és un fil separat que pot executar codi JavaScript de manera independent del fil principal.

Exemple Pràctic

Crear un Worker Thread

  1. Instal·lació i Configuració:

    • No cal instal·lar cap paquet addicional, ja que el mòdul worker_threads és part del nucli de Node.js.
  2. Codi del Fil Principal:

    // main.js
    const { Worker } = require('worker_threads');
    
    function runService(workerData) {
      return new Promise((resolve, reject) => {
        const worker = new Worker('./worker.js', { workerData });
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.on('exit', (code) => {
          if (code !== 0)
            reject(new Error(`Worker stopped with exit code ${code}`));
        });
      });
    }
    
    runService('Hello, Worker!')
      .then(result => console.log(result))
      .catch(err => console.error(err));
    
  3. Codi del Worker:

    // worker.js
    const { parentPort, workerData } = require('worker_threads');
    
    // Simulació d'una tasca intensiva
    let result = 0;
    for (let i = 0; i < 1e9; i++) {
      result += i;
    }
    
    // Enviar el resultat al fil principal
    parentPort.postMessage(`Worker received: ${workerData}, Result: ${result}`);
    

Explicació del Codi

  • Fil Principal (main.js):

    • Importem el mòdul worker_threads i creem una funció runService que accepta workerData.
    • La funció crea un nou Worker que executa el codi de worker.js.
    • Utilitzem promeses per gestionar la comunicació amb el Worker.
    • El Worker envia missatges al fil principal amb worker.on('message', resolve).
  • Worker (worker.js):

    • Importem parentPort i workerData del mòdul worker_threads.
    • Realitzem una tasca intensiva (un bucle que suma números).
    • Enviem el resultat al fil principal amb parentPort.postMessage.

Exercici Pràctic

Exercici 1: Càlcul de Factorials

  1. Fil Principal:

    // main.js
    const { Worker } = require('worker_threads');
    
    function calculateFactorial(number) {
      return new Promise((resolve, reject) => {
        const worker = new Worker('./factorialWorker.js', { workerData: number });
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.on('exit', (code) => {
          if (code !== 0)
            reject(new Error(`Worker stopped with exit code ${code}`));
        });
      });
    }
    
    calculateFactorial(10)
      .then(result => console.log(`Factorial is: ${result}`))
      .catch(err => console.error(err));
    
  2. Worker:

    // factorialWorker.js
    const { parentPort, workerData } = require('worker_threads');
    
    function factorial(n) {
      if (n === 0 || n === 1) return 1;
      return n * factorial(n - 1);
    }
    
    const result = factorial(workerData);
    parentPort.postMessage(result);
    

Solució

  • Fil Principal:

    • Creem un Worker que calcula el factorial d'un número.
    • Utilitzem promeses per gestionar la comunicació amb el Worker.
  • Worker:

    • Implementem una funció recursiva per calcular el factorial.
    • Enviem el resultat al fil principal.

Errors Comuns i Consells

  1. No oblidar gestionar els errors:

    • Sempre afegiu gestors d'errors (worker.on('error', reject)) per capturar i gestionar errors en els Workers.
  2. Evitar tasques intensives en el fil principal:

    • Utilitzeu Workers per a tasques que requereixen molta CPU per evitar bloquejar el fil principal.
  3. Comunicació entre fils:

    • Utilitzeu parentPort.postMessage per enviar dades entre el fil principal i els Workers.

Conclusió

Els Worker Threads són una eina poderosa per millorar el rendiment de les aplicacions Node.js, especialment per a tasques intensives en CPU. Amb una comprensió clara de com crear i gestionar Workers, podeu aprofitar al màxim aquesta funcionalitat per construir aplicacions més eficients i responsives.

Curs de Node.js

Mòdul 1: Introducció a Node.js

Mòdul 2: Conceptes Bàsics

Mòdul 3: Sistema de Fitxers i I/O

Mòdul 4: HTTP i Servidors Web

Mòdul 5: NPM i Gestió de Paquets

Mòdul 6: Framework Express.js

Mòdul 7: Bases de Dades i ORMs

Mòdul 8: Autenticació i Autorització

Mòdul 9: Proves i Depuració

Mòdul 10: Temes Avançats

Mòdul 11: Desplegament i DevOps

Mòdul 12: Projectes del Món Real

© Copyright 2024. Tots els drets reservats