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
-
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.
-
Mòdul
worker_threads
:- Aquest mòdul proporciona una API per crear i gestionar fils de treball (workers).
-
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
-
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.
- No cal instal·lar cap paquet addicional, ja que el mòdul
-
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));
-
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 acceptaworkerData
. - 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)
.
- Importem el mòdul
-
Worker (
worker.js
):- Importem
parentPort
iworkerData
del mòdulworker_threads
. - Realitzem una tasca intensiva (un bucle que suma números).
- Enviem el resultat al fil principal amb
parentPort.postMessage
.
- Importem
Exercici Pràctic
Exercici 1: Càlcul de Factorials
-
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));
-
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
-
No oblidar gestionar els errors:
- Sempre afegiu gestors d'errors (
worker.on('error', reject)
) per capturar i gestionar errors en els Workers.
- Sempre afegiu gestors d'errors (
-
Evitar tasques intensives en el fil principal:
- Utilitzeu Workers per a tasques que requereixen molta CPU per evitar bloquejar el fil principal.
-
Comunicació entre fils:
- Utilitzeu
parentPort.postMessage
per enviar dades entre el fil principal i els Workers.
- Utilitzeu
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
- Introducció a Express.js
- Configuració d'una Aplicació Express
- Middleware
- Routing en Express
- Gestió d'Errors
Mòdul 7: Bases de Dades i ORMs
- Introducció a les Bases de Dades
- Utilitzar MongoDB amb Mongoose
- Utilitzar Bases de Dades SQL amb Sequelize
- Operacions CRUD
Mòdul 8: Autenticació i Autorització
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries amb Mocha i Chai
- Proves d'Integració
- Depuració d'Aplicacions Node.js
Mòdul 10: Temes Avançats
Mòdul 11: Desplegament i DevOps
- Variables d'Entorn
- Utilitzar PM2 per a la Gestió de Processos
- Desplegar a Heroku
- Integració i Desplegament Continu