Introducció
En aquest tema, explorarem els conceptes de callbacks i programació asíncrona en Node.js. La programació asíncrona és una característica fonamental de Node.js que permet gestionar operacions d'entrada/sortida (I/O) de manera eficient sense bloquejar el fil principal d'execució.
Què és un Callback?
Un callback és una funció que es passa com a argument a una altra funció i que s'executa després que aquesta funció hagi completat la seva tasca. Els callbacks són essencials per a la programació asíncrona en Node.js.
Exemple de Callback
function saludar(nom, callback) {
    console.log('Hola, ' + nom + '!');
    callback();
}
function despedir() {
    console.log('Adéu!');
}
saludar('Joan', despedir);Explicació:
- Definim una funció 
saludarque accepta un nom i un callback. - La funció 
saludarimprimeix un missatge de salutació i després crida el callback. - Definim una funció 
despedirque imprimeix un missatge de comiat. - Cridem la funció 
saludarpassant-li el nom 'Joan' i la funciódespedircom a callback. 
Programació Asíncrona
La programació asíncrona permet que el codi continuï executant-se mentre es realitzen operacions que poden trigar temps, com ara la lectura de fitxers o la consulta a una base de dades. Això és especialment important en Node.js, ja que utilitza un sol fil d'execució.
Exemple d'Operació Asíncrona
const fs = require('fs');
fs.readFile('fitxer.txt', 'utf8', (err, data) => {
    if (err) {
        console.error('Error llegint el fitxer:', err);
        return;
    }
    console.log('Contingut del fitxer:', data);
});
console.log('Aquesta línia s\'executa abans que la lectura del fitxer es completi.');Explicació:
- Utilitzem el mòdul 
fsper llegir un fitxer de manera asíncrona. - La funció 
readFileaccepta un callback que es crida quan la lectura del fitxer es completa. - Si hi ha un error, es mostra un missatge d'error.
 - Si la lectura és exitosa, es mostra el contingut del fitxer.
 - La línia 
console.logfora dereadFiles'executa immediatament, abans que la lectura del fitxer es completi. 
Errors Comuns amb Callbacks
Callback Hell
Quan es fan moltes operacions asíncrones en seqüència, els callbacks poden anidar-se profundament, creant un codi difícil de llegir i mantenir. Això es coneix com a "callback hell".
Exemple de Callback Hell:
fs.readFile('fitxer1.txt', 'utf8', (err, data1) => {
    if (err) {
        console.error('Error llegint fitxer1:', err);
        return;
    }
    fs.readFile('fitxer2.txt', 'utf8', (err, data2) => {
        if (err) {
            console.error('Error llegint fitxer2:', err);
            return;
        }
        fs.readFile('fitxer3.txt', 'utf8', (err, data3) => {
            if (err) {
                console.error('Error llegint fitxer3:', err);
                return;
            }
            console.log('Contingut dels fitxers:', data1, data2, data3);
        });
    });
});Solució: Promises i Async/Await
Per evitar el "callback hell", es poden utilitzar Promises i la sintaxi async/await.
Exemple amb Promises:
const fs = require('fs').promises;
fs.readFile('fitxer1.txt', 'utf8')
    .then(data1 => {
        return fs.readFile('fitxer2.txt', 'utf8');
    })
    .then(data2 => {
        return fs.readFile('fitxer3.txt', 'utf8');
    })
    .then(data3 => {
        console.log('Contingut dels fitxers:', data1, data2, data3);
    })
    .catch(err => {
        console.error('Error llegint els fitxers:', err);
    });Exemple amb Async/Await:
const fs = require('fs').promises;
async function llegirFitxers() {
    try {
        const data1 = await fs.readFile('fitxer1.txt', 'utf8');
        const data2 = await fs.readFile('fitxer2.txt', 'utf8');
        const data3 = await fs.readFile('fitxer3.txt', 'utf8');
        console.log('Contingut dels fitxers:', data1, data2, data3);
    } catch (err) {
        console.error('Error llegint els fitxers:', err);
    }
}
llegirFitxers();Exercicis Pràctics
Exercici 1: Callback Bàsic
Escriu una funció ferCalcul que accepti dos números i un callback. La funció ha de sumar els dos números i passar el resultat al callback.
function ferCalcul(num1, num2, callback) {
    // Escriu el teu codi aquí
}
// Exemple d'ús:
ferCalcul(5, 10, resultat => {
    console.log('El resultat és:', resultat);
});Solució:
function ferCalcul(num1, num2, callback) {
    const resultat = num1 + num2;
    callback(resultat);
}
// Exemple d'ús:
ferCalcul(5, 10, resultat => {
    console.log('El resultat és:', resultat);
});Exercici 2: Lectura Asíncrona de Fitxers
Utilitza fs.readFile per llegir el contingut de dos fitxers de manera asíncrona i mostrar el contingut combinat.
Solució:
const fs = require('fs');
function llegirFitxers() {
    fs.readFile('fitxer1.txt', 'utf8', (err, data1) => {
        if (err) {
            console.error('Error llegint fitxer1:', err);
            return;
        }
        fs.readFile('fitxer2.txt', 'utf8', (err, data2) => {
            if (err) {
                console.error('Error llegint fitxer2:', err);
                return;
            }
            console.log('Contingut combinat:', data1 + data2);
        });
    });
}
llegirFitxers();Conclusió
En aquesta secció, hem après què són els callbacks i com s'utilitzen per a la programació asíncrona en Node.js. També hem vist com evitar el "callback hell" utilitzant Promises i async/await. Aquests conceptes són fonamentals per escriure codi eficient i mantenible en Node.js. En el proper mòdul, explorarem els mòduls i la funció require() per organitzar millor el nostre codi.
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
 
