Amb l'entorn instal·lat i la carpeta escena-viva/ creada, és el moment d'escriure codi. En aquesta lliçó construirem el primer programa real del projecte: src/cataleg.js, un script que defineix el catàleg d'esdeveniments d'Escena Viva i el mostra per consola, amb la possibilitat de filtrar-lo per sala des de la línia d'ordres.

Pel camí descobriràs les diferències pràctiques entre executar JavaScript al navegador i a Node.js, coneixeràs l'objecte process, aprendràs a distingir la sortida estàndard de la sortida d'error i sabràs què significa el codi de sortida d'un programa. Són conceptes que semblen menors i que resulten fonamentals tan bon punt el teu codi deixa de ser un exercici i passa a integrar-se en un servidor o en una canonada de desplegament.

Contingut

  1. Escriure i executar el primer script
  2. El navegador i Node.js: el que hi ha i el que no
  3. L'objecte process: la finestra al sistema
  4. El catàleg d'Escena Viva: src/cataleg.js
  5. Mostrar dades: console.log, console.table i plantilles de cadena
  6. Llegir arguments amb process.argv
  7. console.error, stdout i stderr
  8. Codis de sortida i process.exit
  9. Depurar el típic error de sintaxi
  10. Què no fa encara aquest programa

  1. Escriure i executar el primer script

Situa't a la carpeta del projecte i crea un fitxer de prova dins de src/:

cd escena-viva

Crea src/hola.js amb aquest contingut:

// src/hola.js
// El primer programa del curs: comprovar que Node executa el nostre codi.

console.log('Escena Viva: entorn operatiu');
console.log('Versio de Node:', process.version);
console.log('Directori de treball:', process.cwd());

Executa'l:

node src/hola.js
Escena Viva: entorn operatiu
Versio de Node: v24.5.0
Directori de treball: /home/usuari/projectes/escena-viva

Tres detalls importants d'aquesta primera execució:

  • La ruta és relativa al directori des del qual executes node, no al fitxer. Si fossis dins de src/, l'ordre seria node hola.js.
  • L'extensió .js és opcional: node src/hola també funciona. Escriu-la sempre igualment; és més clar.
  • No hi ha compilació ni configuració prèvia. No cal package.json, ni instal·lar res, ni declarar un main. Node llegeix el fitxer i l'executa.

  1. El navegador i Node.js: el que hi ha i el que no

Si véns del desenvolupament front-end, el teu instint serà fer servir coses que aquí no existeixen. Comprovem-ho:

// src/diferencies.js
// Quins objectes globals existeixen a Node i quins no.

console.log('typeof window   :', typeof window);     // undefined
console.log('typeof document :', typeof document);   // undefined
console.log('typeof alert    :', typeof alert);      // undefined
console.log('typeof global   :', typeof global);     // object
console.log('typeof process  :', typeof process);    // object
console.log('typeof console  :', typeof console);    // object
console.log('typeof fetch    :', typeof fetch);      // function
node src/diferencies.js
typeof window   : undefined
typeof document : undefined
typeof alert    : undefined
typeof global   : object
typeof process  : object
typeof console  : object
typeof fetch    : function

Resum d'equivalències:

Tasca Navegador Node.js
Objecte global window global
Objecte global (estàndard en tots dos) globalThis globalThis
Mostrar informació console.log, alert console.log (no hi ha alert)
Manipular la interfície document.querySelector(...) No existeix: no hi ha interfície
Petició HTTP fetch (amb restriccions CORS) fetch (sense CORS) o mòduls http/https
Desar dades localment localStorage Fitxers (fs) o base de dades
Llegir paràmetres d'entrada location.search process.argv
Variables de configuració Incrustades al bundle process.env
Acabar l'execució Tancar la pestanya process.exit()
Temporitzadors setTimeout, setInterval Els mateixos, més setImmediate

console.log funciona en tots dos entorns, però no fa el mateix: al navegador escriu a la consola de les eines de desenvolupament; a Node escriu a la sortida estàndard del procés, que és el que veus al terminal i el que es pot redirigir a un fitxer o a un altre programa. Hi tornarem a l'apartat 7.

  1. L'objecte process: la finestra al sistema

process és un objecte global que representa el procés del sistema operatiu en què corre el teu programa. És la porta d'entrada a tot el que envolta el teu codi.

Propietat o mètode Què ofereix
process.argv Array amb els arguments de la línia d'ordres
process.env Objecte amb les variables d'entorn
process.version Versió de Node (v24.5.0)
process.platform 'linux', 'darwin', 'win32'
process.cwd() Directori de treball actual
process.uptime() Segons que fa que el procés és viu
process.memoryUsage() Ús de memòria en bytes
process.exit(codi) Acaba el procés amb un codi de sortida
process.exitCode Fixa el codi de sortida sense tallar l'execució
process.stdout / process.stderr Fluxos de sortida estàndard i d'error

Un exemple útil per diagnosticar entorns:

// src/entorn.js
// Diagnostic rapid de l'entorn d'execucio d'Escena Viva.

const memoria = process.memoryUsage();

console.log(`Node        : ${process.version}`);
console.log(`Plataforma  : ${process.platform}`);
console.log(`Directori   : ${process.cwd()}`);
console.log(`Memoria heap: ${Math.round(memoria.heapUsed / 1024 / 1024)} MB`);
Node        : v24.5.0
Plataforma  : linux
Directori   : /home/usuari/projectes/escena-viva
Memoria heap: 5 MB

  1. El catàleg d'Escena Viva: src/cataleg.js

Ara el programa de debò. Escena Viva gestiona esdeveniments en tres sales: Teatro Almendra, Sala Bóveda i Auditorio Ribera. Cada esdeveniment té una o diverses sessions, i cada sessió té data, aforament, entrades venudes i preu.

Una decisió de disseny que adoptem des del primer minut: els preus es desen en cèntims, com a nombre enter. Mai 25.50, sempre 2550. La raó és que el tipus number de JavaScript és de coma flotant i produeix sorpreses com 0.1 + 0.2 === 0.30000000000000004. Amb diners això és inacceptable. Formalitzarem aquesta i altres convencions a El Projecte del Curs.

Crea src/cataleg.js:

// src/cataleg.js
// Cataleg d'esdeveniments d'Escena Viva.
// De moment les dades estan escrites al propi fitxer; al modul 3
// les llegirem des de dades/esdeveniments.json.

const cataleg = [
  {
    id: 'evt-001',
    titol: 'Concierto de Otono',
    sala: 'Teatro Almendra',
    categoria: 'concert',
    duracioMinuts: 95,
    sessions: [
      { id: 'ses-001-1', dataHora: '2026-10-03T20:00:00', aforament: 420, venudes: 180, preuCentims: 2500 },
      { id: 'ses-001-2', dataHora: '2026-10-04T19:00:00', aforament: 420, venudes: 96,  preuCentims: 2200 }
    ]
  },
  {
    id: 'evt-002',
    titol: 'Noche de Monologos',
    sala: 'Sala Boveda',
    categoria: 'humor',
    duracioMinuts: 80,
    sessions: [
      { id: 'ses-002-1', dataHora: '2026-10-10T21:30:00', aforament: 120, venudes: 118, preuCentims: 1800 },
      { id: 'ses-002-2', dataHora: '2026-10-11T21:30:00', aforament: 120, venudes: 45,  preuCentims: 1800 },
      { id: 'ses-002-3', dataHora: '2026-10-17T21:30:00', aforament: 120, venudes: 12,  preuCentims: 1500 }
    ]
  },
  {
    id: 'evt-003',
    titol: 'Festival de Jazz de Primavera',
    sala: 'Auditorio Ribera',
    categoria: 'festival',
    duracioMinuts: 240,
    sessions: [
      { id: 'ses-003-1', dataHora: '2027-04-17T19:00:00', aforament: 900, venudes: 640, preuCentims: 3800 },
      { id: 'ses-003-2', dataHora: '2027-04-18T19:00:00', aforament: 900, venudes: 720, preuCentims: 4200 }
    ]
  }
];

Fixa't en un detall deliberat: els valors de text que formaran part d'identificadors o de noms de fitxer eviten accents i ñ (Concierto de Otono, Sala Boveda). A les dades que es mostren a l'usuari final acabarem fent servir l'ortografia correcta, però mentre treballem per consola i amb noms tècnics, mantenir-ho simple estalvia problemes de codificació. És una convenció del projecte, no una limitació de Node.

  1. Mostrar dades: console.log, console.table i plantilles de cadena

Afegeix a continuació, al mateix fitxer, una funció que formati el preu i una altra que imprimeixi el catàleg.

// --- Utilitats de presentacio ---

// Converteix 2500 (centims) en la cadena "25,00 EUR".
function formatarPreu(centims) {
  const euros = Math.floor(centims / 100);
  const resta = String(centims % 100).padStart(2, '0');
  return `${euros},${resta} EUR`;
}

// Converteix "2026-10-03T20:00:00" en "03/10/2026 20:00".
function formatarData(dataISO) {
  const data = new Date(dataISO);
  const dia = String(data.getDate()).padStart(2, '0');
  const mes = String(data.getMonth() + 1).padStart(2, '0');
  const any = data.getFullYear();
  const hora = String(data.getHours()).padStart(2, '0');
  const minut = String(data.getMinutes()).padStart(2, '0');
  return `${dia}/${mes}/${any} ${hora}:${minut}`;
}

Explicació de les peces noves per a qui vingui amb JavaScript bàsic:

  • Plantilles de cadena (cometes invertides): `${euros},${resta} EUR` permet incrustar expressions dins d'una cadena sense concatenar amb +. És més llegible i admet salts de línia reals.
  • padStart(2, '0'): omple per l'esquerra fins a arribar a 2 caràcters. Converteix 5 en "05", que és el que volem en dates i cèntims.
  • Math.floor(2500 / 100) dona els euros sencers; 2500 % 100 dona els cèntims sobrants. Treballant sempre amb enters no hi ha errors d'arrodoniment.

Ara la impressió del llistat:

// --- Presentacio del cataleg ---

function mostrarCataleg(esdeveniments) {
  console.log('');
  console.log('==========================================');
  console.log("   ESCENA VIVA - CATALEG D'ESDEVENIMENTS");
  console.log('==========================================');

  for (const esdeveniment of esdeveniments) {
    // Total d'entrades disponibles sumant totes les sessions.
    let disponiblesTotals = 0;
    for (const sessio of esdeveniment.sessions) {
      disponiblesTotals += sessio.aforament - sessio.venudes;
    }

    console.log('');
    console.log(`${esdeveniment.titol}  [${esdeveniment.id}]`);
    console.log(`  Sala      : ${esdeveniment.sala}`);
    console.log(`  Categoria : ${esdeveniment.categoria}`);
    console.log(`  Durada    : ${esdeveniment.duracioMinuts} min`);
    console.log(`  Sessions  : ${esdeveniment.sessions.length}`);
    console.log(`  Lliures   : ${disponiblesTotals} entrades`);

    for (const sessio of esdeveniment.sessions) {
      const lliures = sessio.aforament - sessio.venudes;
      const ocupacio = Math.round((sessio.venudes / sessio.aforament) * 100);
      console.log(
        `    - ${formatarData(sessio.dataHora)}  ` +
        `${formatarPreu(sessio.preuCentims)}  ` +
        `${lliures}/${sessio.aforament} lliures  (${ocupacio}% ocupat)`
      );
    }
  }

  console.log('');
}

console.table: una taula sense esforç

Node inclou console.table, que dibuixa un array d'objectes com a taula ASCII. És ideal per inspeccionar dades ràpidament.

// Vista compacta en forma de taula.
function mostrarTaulaResum(esdeveniments) {
  // Construim un array "pla": console.table espera objectes simples.
  const files = esdeveniments.map((esdeveniment) => {
    let aforamentTotal = 0;
    let venudesTotals = 0;
    for (const sessio of esdeveniment.sessions) {
      aforamentTotal += sessio.aforament;
      venudesTotals += sessio.venudes;
    }

    return {
      Esdeveniment: esdeveniment.titol,
      Sala: esdeveniment.sala,
      Sessions: esdeveniment.sessions.length,
      Aforament: aforamentTotal,
      Venudes: venudesTotals,
      Ocupacio: `${Math.round((venudesTotals / aforamentTotal) * 100)}%`
    };
  });

  console.table(files);
}

Sortida:

┌─────────┬─────────────────────────────────┬────────────────────┬──────────┬───────────┬─────────┬──────────┐
│ (index) │ Esdeveniment                    │ Sala               │ Sessions │ Aforament │ Venudes │ Ocupacio │
├─────────┼─────────────────────────────────┼────────────────────┼──────────┼───────────┼─────────┼──────────┤
│ 0       │ 'Concierto de Otono'            │ 'Teatro Almendra'  │ 2        │ 840       │ 276     │ '33%'    │
│ 1       │ 'Noche de Monologos'            │ 'Sala Boveda'      │ 3        │ 360       │ 175     │ '49%'    │
│ 2       │ 'Festival de Jazz de Primavera' │ 'Auditorio Ribera' │ 2        │ 1800      │ 1360    │ '76%'    │
└─────────┴─────────────────────────────────┴────────────────────┴──────────┴───────────┴─────────┴──────────┘

Altres mètodes de console que convé conèixer:

Mètode Ús
console.log(...) Sortida normal (stdout)
console.error(...) Sortida d'error (stderr)
console.warn(...) Igual que error: va a stderr
console.table(array) Taula ASCII
console.dir(obj, { depth: null }) Inspecciona un objecte imbricat sense retallar-lo
console.time('t') / console.timeEnd('t') Mesura quant triga un bloc
console.count('x') Compta quantes vegades es passa per un punt

  1. Llegir arguments amb process.argv

Volem poder executar:

node src/cataleg.js "Sala Boveda"

i veure només els esdeveniments d'aquella sala. Els arguments arriben a process.argv, un array de cadenes.

// Vegem primer que conte exactament process.argv
console.log(process.argv);
node src/cataleg.js "Sala Boveda" --taula
[
  '/home/usuari/.nvm/versions/node/v24.5.0/bin/node',
  '/home/usuari/projectes/escena-viva/src/cataleg.js',
  'Sala Boveda',
  '--taula'
]

L'estructura és sempre la mateixa:

Índex Contingut
0 Ruta absoluta de l'executable de Node
1 Ruta absoluta de l'script executat
2 en endavant Els arguments que ha escrit l'usuari

D'aquí ve l'idioma habitual: process.argv.slice(2).

// --- Lectura d'arguments ---

const parametres = process.argv.slice(2);

// El primer parametre que no comenci per "--" s'interpreta com a sala.
const salaFiltre = parametres.find((param) => !param.startsWith('--'));
const usarTaula = parametres.includes('--taula');

// Filtrem el cataleg si s'ha indicat una sala.
let esdevenimentsMostrats = cataleg;

if (salaFiltre) {
  esdevenimentsMostrats = cataleg.filter(
    (esdeveniment) => esdeveniment.sala.toLowerCase() === salaFiltre.toLowerCase()
  );
}

Comparar en minúscules amb toLowerCase() fa el filtre tolerant: "sala boveda" i "Sala Boveda" funcionen igual. És un detall petit amb un gran efecte en la usabilitat d'una eina de línia d'ordres.

Per a arguments més complexos (opcions amb valor, indicadors combinats), Node inclou util.parseArgs, i l'ecosistema ofereix paquets com commander o yargs. Els veurem quan arribem a npm al Mòdul 5.

  1. console.error, stdout i stderr

Tot procés del sistema operatiu disposa de dos canals de sortida separats:

  • stdout (sortida estàndard): el resultat útil del programa.
  • stderr (sortida d'error): missatges d'error, avisos i diagnòstics.

Estan separats per una raó pràctica: permet redirigir el resultat a un fitxer sense barrejar-lo amb els errors.

# Nomes el cataleg va al fitxer; els errors continuen apareixent a pantalla
node src/cataleg.js > informes/cataleg.txt

# Redirigir tambe els errors a un altre fitxer
node src/cataleg.js > informes/cataleg.txt 2> informes/errors.txt
flowchart LR
    P["Proces Node<br/>src/cataleg.js"] -->|"stdout (1)<br/>console.log"| A["Terminal o<br/>informes/cataleg.txt"]
    P -->|"stderr (2)<br/>console.error"| B["Terminal o<br/>informes/errors.txt"]

Si barreges errors dins de console.log, qui redirigeixi la teva sortida a un fitxer es trobarà missatges d'error incrustats entre les dades. Regla: les dades per console.log, tota la resta per console.error.

Apliquem-ho al filtre per sala:

// --- Validacio del filtre ---

if (salaFiltre && esdevenimentsMostrats.length === 0) {
  // Aixo es un diagnostic, no una dada: va a stderr.
  console.error(`Error: no hi ha esdeveniments a la sala "${salaFiltre}".`);
  console.error('Sales disponibles:');
  for (const sala of new Set(cataleg.map((esdeveniment) => esdeveniment.sala))) {
    console.error(`  - ${sala}`);
  }
  process.exit(1);
}

new Set(...) elimina duplicats: si dos esdeveniments comparteixen sala, només apareix un cop. Ho veurem amb més calma a JavaScript Modern per a Node.js.

  1. Codis de sortida i process.exit

Quan un programa acaba, retorna al sistema operatiu un nombre enter: el codi de sortida.

Codi Significat convencional
0 Èxit
1 Error genèric
2 Ús incorrecte (arguments mal escrits)
> 2 Codis específics que defineix la teva aplicació

El pots consultar després d'executar una ordre:

node src/cataleg.js "Sala Inexistent"
echo $?          # Linux/macOS -> imprimeix 1
node src\cataleg.js "Sala Inexistent"
$LASTEXITCODE    # Windows PowerShell -> imprimeix 1

Això és el que permet encadenar ordres amb seguretat en un desplegament:

# L'informe nomes es genera si el cataleg s'ha validat correctament
node src/cataleg.js --validar && node src/informe.js

process.exit() amb responsabilitat

process.exit(1) talla el procés immediatament. És un instrument contundent: si hi ha escriptures de fitxer o respostes de xarxa pendents, poden quedar-se a mitges.

L'alternativa recomanada en la majoria de casos és assignar process.exitCode i deixar que el programa acabi de manera natural:

// Preferible: marca el codi de sortida i deixa acabar netament
if (salaFiltre && esdevenimentsMostrats.length === 0) {
  console.error(`Error: no hi ha esdeveniments a la sala "${salaFiltre}".`);
  process.exitCode = 1;
  return;   // Si som dins d'una funcio
}
Forma Quan fer-la servir
process.exitCode = 1 Gairebé sempre: segur, deixa que es completin les tasques pendents
process.exit(1) Errors fatals en scripts senzills, o quan has de tallar sense remei

Tanquem el fitxer amb l'execució:

// --- Execucio ---

if (usarTaula) {
  mostrarTaulaResum(esdevenimentsMostrats);
} else {
  mostrarCataleg(esdevenimentsMostrats);
}

console.log(`Total: ${esdevenimentsMostrats.length} esdeveniment(s) mostrat(s).`);

Prova-ho:

node src/cataleg.js                        # Tot el cataleg, format detallat
node src/cataleg.js --taula                # Tot el cataleg, format taula
node src/cataleg.js "Teatro Almendra"      # Nomes una sala
node src/cataleg.js "Sala Inexistent"      # Error controlat, codi de sortida 1

  1. Depurar el típic error de sintaxi

Introdueix deliberadament una errada: esborra una clau de tancament de l'array cataleg i executa l'script.

/home/usuari/projectes/escena-viva/src/cataleg.js:34
];
 ^

SyntaxError: Unexpected token ']'
    at wrapSafe (node:internal/modules/cjs/loader:1281:20)
    at Module._compile (node:internal/modules/cjs/loader:1321:27)
    ...

Node.js v24.5.0

Com llegir aquest missatge, de dalt a baix:

  1. .../src/cataleg.js:34: fitxer i línia on Node s'ha adonat del problema.
  2. El fragment de codi i el ^: el token exacte que no encaixava.
  3. SyntaxError: Unexpected token ']': el tipus d'error.
  4. La pila de crides (at wrapSafe...): en errors de sintaxi són funcions internes de Node; ignora-la, no aporta res.

Punt clau que confon molta gent: la línia que indica Node és on l'analitzador s'ha ennuegat, no necessàriament on és l'errada. Si oblides una clau a la línia 20, l'error pot assenyalar la 34. Busca cap amunt des de la línia indicada.

Errors freqüents i el seu missatge:

Missatge Causa habitual
SyntaxError: Unexpected token '}' Clau, parèntesi o claudàtor de més o mal tancat
SyntaxError: Unexpected end of input Falta un tancament al final del fitxer
ReferenceError: cataleg is not defined Nom mal escrit o variable feta servir abans de declarar-la
TypeError: Cannot read properties of undefined (reading 'sessions') Has accedit a una propietat d'una cosa que val undefined
Error: Cannot find module '/ruta/src/catalog.js' Nom de fitxer o ruta equivocats

Aquest últim és molt típic al principi: Cannot find module gairebé sempre vol dir que has executat node cataleg.js des de l'arrel en comptes de node src/cataleg.js.

Un editor amb ESLint t'hauria marcat l'error abans de desar. Per això la lliçó anterior insistia a configurar-lo.

  1. Què no fa encara aquest programa

És tan important saber què has construït com què et falta:

Limitació actual On es resol
Les dades estan escrites dins del .js; canviar el catàleg obliga a tocar codi Mòdul 3: llegirem dades/esdeveniments.json amb fs
Només es veu per terminal; no hi ha manera de consultar-ho des d'un navegador Mòdul 4: servirem el catàleg per HTTP
Tot el codi viu en un únic fitxer Mòdul 2: separarem en mòduls amb require/module.exports
No hi ha persistència de comandes ni usuaris Mòdul 7: base de dades escena_viva
L'anàlisi d'arguments és artesanal Mòdul 5: paquets especialitzats

Aquest és exactament el camí del curs: el mateix src/cataleg.js anirà creixent i transformant-se mòdul a mòdul fins a ser una API real.

Errors Comuns i Consells

Error 1: fer servir window, document o alert. No existeixen a Node. Si un tutorial els fa servir, està parlant del navegador.

Error 2: creure que process.argv[0] és el primer argument de l'usuari. És la ruta de l'executable de Node. Els arguments de l'usuari comencen a l'índex 2; fes servir sempre process.argv.slice(2).

Error 3: enviar els errors per console.log. Contamina la sortida de dades. Els errors i avisos van per console.error.

Error 4: cridar process.exit() a mitja operació. Talla el procés sense esperar que acabin escriptures pendents. Prefereix process.exitCode.

Error 5: executar l'script des del directori equivocat. Cannot find module sol voler dir això. Comprova process.cwd().

Error 6: buscar l'error de sintaxi exactament a la línia que indica Node. L'analitzador assenyala on ha fallat, no on és el descuit. Mira les línies anteriors.

Consell 1: fes servir console.table per inspeccionar dades. És molt més llegible que un console.log d'un array d'objectes.

Consell 2: mesura amb console.time. Embolcallar un bloc entre console.time('carrega') i console.timeEnd('carrega') és la manera més barata de saber què triga.

Consell 3: pensa els teus scripts com a ordres. Arguments clars, dades per stdout, errors per stderr i codi de sortida correcte. Així els podràs encadenar amb altres eines.

Exercicis

Exercici 1: informació de l'entorn

Crea src/entorn.js que imprimeixi una taula (amb console.table) amb aquestes files: versió de Node, plataforma, arquitectura (process.arch), directori de treball, nombre d'arguments rebuts i memòria heap usada en MB. Executa'l amb i sense arguments extra i comprova que el recompte canvia.

Exercici 2: filtre per preu màxim

Amplia src/cataleg.js per acceptar un segon filtre: --max=2000 ha de mostrar només els esdeveniments que tinguin almenys una sessió amb un preuCentims menor o igual a aquest valor. Requisits:

  • S'ha de poder combinar amb el filtre de sala: node src/cataleg.js "Sala Boveda" --max=1600.
  • Si el valor de --max no és un nombre vàlid, escriu un missatge per console.error i acaba amb codi de sortida 2.

Exercici 3: informe d'ocupació amb codi de sortida

Crea src/alerta-aforament.js que recorri el catàleg i llisti per console.log totes les sessions amb menys del 20% d'entrades venudes (les que cal promocionar). Regles:

  • Format de cada línia: evt-002 | ses-002-3 | 17/10/2026 21:30 | 10% venut.
  • Si no hi ha cap sessió en aquesta situació, escriu Sense sessions en risc i acaba amb codi 0.
  • Si n'hi ha alguna, acaba amb codi de sortida 1, perquè un sistema d'avisos ho pugui detectar.

Solucions

Solució 1

// src/entorn.js
// Diagnostic de l'entorn d'execucio en forma de taula.

const memoria = process.memoryUsage();
const parametres = process.argv.slice(2);

const dades = [
  { Dada: 'Versio de Node',  Valor: process.version },
  { Dada: 'Plataforma',      Valor: process.platform },
  { Dada: 'Arquitectura',    Valor: process.arch },
  { Dada: 'Directori',       Valor: process.cwd() },
  { Dada: 'Arguments',       Valor: parametres.length },
  { Dada: 'Heap usat (MB)',  Valor: Math.round(memoria.heapUsed / 1024 / 1024) }
];

console.table(dades);
node src/entorn.js
node src/entorn.js un dos tres    # La fila "Arguments" passa a valer 3

Solució 2

// --- Filtre per preu maxim ---

// Busquem un parametre amb la forma --max=NNNN
const parametreMax = parametres.find((param) => param.startsWith('--max='));

if (parametreMax) {
  // Tot el que hi ha despres del signe "=" es el valor.
  const valorText = parametreMax.split('=')[1];
  const preuMaxim = Number(valorText);

  // Number('abc') retorna NaN; Number('') retorna 0, que tampoc no val aqui.
  if (!Number.isInteger(preuMaxim) || preuMaxim <= 0) {
    console.error(`Error: valor invalid a --max ("${valorText}").`);
    console.error('Us: node src/cataleg.js [sala] [--max=CENTIMS] [--taula]');
    process.exit(2);   // 2 = us incorrecte
  }

  esdevenimentsMostrats = esdevenimentsMostrats.filter((esdeveniment) =>
    // some() retorna true si ALMENYS una sessio compleix la condicio.
    esdeveniment.sessions.some((sessio) => sessio.preuCentims <= preuMaxim)
  );
}

Aquest bloc s'ha de col·locar després del filtre de sala, perquè tots dos es combinin: cada filtre redueix el resultat de l'anterior.

node src/cataleg.js --max=2000           # Noche de Monologos (1800 i 1500)
node src/cataleg.js "Sala Boveda" --max=1600   # Nomes per la sessio de 1500
node src/cataleg.js --max=abc            # Error, codi de sortida 2

Solució 3

// src/alerta-aforament.js
// Llista les sessions amb venda baixa per llancar accions de promocio.

const cataleg = require('./cataleg-dades.js'); // (veure nota al final)

const LLINDAR_PERCENTATGE = 20;
const enRisc = [];

for (const esdeveniment of cataleg) {
  for (const sessio of esdeveniment.sessions) {
    const percentatge = Math.round((sessio.venudes / sessio.aforament) * 100);

    if (percentatge < LLINDAR_PERCENTATGE) {
      enRisc.push({ esdeveniment, sessio, percentatge });
    }
  }
}

if (enRisc.length === 0) {
  console.log('Sense sessions en risc');
  process.exitCode = 0;
} else {
  for (const element of enRisc) {
    console.log(
      `${element.esdeveniment.id} | ${element.sessio.id} | ` +
      `${formatarData(element.sessio.dataHora)} | ${element.percentatge}% venut`
    );
  }
  // Codi diferent de 0 perque un sistema d'avisos ho detecti.
  process.exitCode = 1;
}

Sortida esperada amb les nostres dades:

evt-002 | ses-002-3 | 17/10/2026 21:30 | 10% venut

Nota sobre el require de la primera línia: perquè aquest segon script faci servir les mateixes dades caldria exportar-les des d'un fitxer comú. Encara no hem vist com fer-ho —és el tema de Mòduls CommonJS i require()—, així que de moment copia l'array cataleg i la funció formatarData dins de src/alerta-aforament.js. Que aquesta duplicació et resulti incòmoda és precisament el motiu pel qual existeixen els mòduls.

Conclusió

Has escrit i executat el teu primer programa real en Node.js. Pel camí has vist que JavaScript al servidor no té window ni document, però sí process, l'objecte que et connecta amb el sistema operatiu: arguments, entorn, directori de treball, memòria i codi de sortida.

Has construït src/cataleg.js amb els tres esdeveniments fundacionals d'Escena Viva —el Concierto de Otoño al Teatro Almendra, la Noche de Monólogos a la Sala Bóveda i el Festival de Jazz de Primavera a l'Auditorio Ribera—, l'has formatat amb plantilles de cadena i console.table, l'has filtrat amb process.argv i has après a separar les dades (stdout) dels diagnòstics (stderr), tancant amb un codi de sortida coherent. També saps llegir un SyntaxError sense espantar-te: fitxer, línia, token i a mirar cap amunt.

Tot això ho has fet editant un fitxer, desant-lo i tornant-lo a executar. Hi ha una manera molt més àgil de provar idees soltes —una expressió, una transformació del catàleg, un dubte sobre com es comporta un mètode— sense aquest cicle de desar i executar. A la lliçó següent, El REPL de Node.js, aprendràs a fer servir l'intèrpret interactiu per explorar les dades d'Escena Viva en directe i provar transformacions abans d'escriure-les a l'script.

Curs de Node.js: De Principiant a Avançat

Mòdul 1: Introducció a Node.js

Mòdul 2: Conceptes Bàsics

Mòdul 3: Sistema de Fitxers i E/S

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 2026. Tots els drets reservats