🚀 JavaScript Async Programming

Învață să stăpânești programarea asincronă în JavaScript

1. Callbacks

Un callback este o funcție care este pasată ca argument unei alte funcții și este executată după ce operațiunea asincronă se termină.

📚 Concepte de bază

// Exemplu simplu de callback
function salutare(nume, callback) {
    console.log('Salut ' + nume);
    callback();
}

salutare('Maria', function() {
    console.log('Callback executat!');
});

⏱️ Callbacks cu setTimeout

Exemplu: Timer cu Callback

function asteapta(milisecunde, callback) {
    setTimeout(() => {
        callback(`Am așteptat ${milisecunde}ms`);
    }, milisecunde);
}

asteapta(2000, (mesaj) => {
    console.log(mesaj); // Se afișează după 2 secunde
});

🔄 Callback Hell

⚠️ Atenție: Callback-urile înlănțuite pot duce la "Callback Hell" - cod greu de citit și menținut.
// Exemplu de Callback Hell
getData(function(a) {
    getMoreData(a, function(b) {
        getMoreData(b, function(c) {
            getMoreData(c, function(d) {
                getMoreData(d, function(e) {
                    console.log(e);
                });
            });
        });
    });
});

🏋️ Exercițiu 1: Callbacks în serie

Creează 3 funcții care se apelează în serie folosind callbacks. Fiecare funcție adaugă un număr la rezultat.

🎮 Demo Interactiv: Animație cu Callbacks

Apasă butoanele pentru a vedea animații în serie folosind callbacks:

2. Promises

Promise reprezintă o valoare care poate fi disponibilă acum, în viitor, sau niciodată. Are 3 stări: pending, fulfilled, rejected.

📚 Creare și utilizare Promise

// Creare Promise
const promisiune = new Promise((resolve, reject) => {
    setTimeout(() => {
        const succes = true;
        if (succes) {
            resolve('Operațiune reușită!');
        } else {
            reject('Operațiune eșuată!');
        }
    }, 2000);
});

// Utilizare Promise
promisiune
    .then(rezultat => console.log(rezultat))
    .catch(eroare => console.error(eroare));

Exemplu: Promise Chain

function multiplicaCu2(numar) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (typeof numar === 'number') {
                resolve(numar * 2);
            } else {
                reject('Nu este un număr!');
            }
        }, 1000);
    });
}

multiplicaCu2(5)
    .then(rezultat => {
        console.log(rezultat); // 10
        return multiplicaCu2(rezultat);
    })
    .then(rezultat => {
        console.log(rezultat); // 20
        return multiplicaCu2(rezultat);
    })
    .then(rezultat => {
        console.log(rezultat); // 40
    })
    .catch(eroare => console.error(eroare));

🔧 Promise.all() și Promise.race()

// Promise.all - așteaptă ca toate să se termine
const promise1 = Promise.resolve(3);
const promise2 = new Promise(resolve => setTimeout(() => resolve(7), 2000));
const promise3 = Promise.resolve(5);

Promise.all([promise1, promise2, promise3])
    .then(valori => console.log(valori)); // [3, 7, 5]

// Promise.race - returnează prima care se termină
Promise.race([promise1, promise2, promise3])
    .then(valoare => console.log(valoare)); // 3

🏋️ Exercițiu 2: Promise Chain Calculator

Creează un calculator care folosește Promises pentru operații matematice în lanț.

🎮 Demo: Promise Race

Vezi care Promise se termină primul!

Racer 1
Racer 2
Racer 3

3. Fetch API

Fetch API oferă o interfață modernă pentru a face cereri HTTP. Returnează un Promise.

📚 Sintaxa de bază

// GET Request simplu
fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Eroare:', error));

// POST Request
fetch('https://api.example.com/users', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: 'Ion',
        email: 'ion@example.com'
    })
})
.then(response => response.json())
.then(data => console.log('Success:', data));

Exemplu: Fetch Users de pe JSONPlaceholder

🔍 Gestionarea erorilor

fetch('https://api.example.com/data')
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
    })
    .then(data => console.log(data))
    .catch(error => console.error('A apărut o problemă:', error));

🏋️ Exercițiu 3: Fetch și afișare date

Folosește Fetch API pentru a obține și afișa informații despre un post specific.

🎮 Demo: API Weather

Obține date meteo simulate pentru diferite orașe:

4. Async/Await

Async/Await este syntactic sugar peste Promises, făcând codul asincron să arate mai mult ca cel sincron.

📚 Sintaxa de bază

// Funcție async
async function getData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Eroare:', error);
    }
}

// Apelare funcție async
getData().then(data => console.log(data));

⚡ Comparație: Promises vs Async/Await

Cu Promises:

function getUserData(userId) {
    return fetch(`/api/user/${userId}`)
        .then(response => response.json())
        .then(user => fetch(`/api/posts/${user.id}`))
        .then(response => response.json())
        .then(posts => {
            console.log('Posts:', posts);
            return posts;
        })
        .catch(error => console.error(error));
}

Cu Async/Await:

async function getUserData(userId) {
    try {
        const userResponse = await fetch(`/api/user/${userId}`);
        const user = await userResponse.json();
        
        const postsResponse = await fetch(`/api/posts/${user.id}`);
        const posts = await postsResponse.json();
        
        console.log('Posts:', posts);
        return posts;
    } catch (error) {
        console.error(error);
    }
}

🔄 Operații paralele cu Async/Await

// Executare în paralel
async function getMultipleData() {
    const [users, posts, comments] = await Promise.all([
        fetch('/api/users').then(r => r.json()),
        fetch('/api/posts').then(r => r.json()),
        fetch('/api/comments').then(r => r.json())
    ]);
    
    return { users, posts, comments };
}

🏋️ Exercițiu 4: Async/Await Chain

Folosește async/await pentru a obține date despre un user și postările sale.

🎮 Demo Final: Todo App cu Async/Await

Aplicație completă folosind toate conceptele învățate:

🎉 Felicitări!

Ai parcurs toate conceptele de bază ale programării asincrone în JavaScript!

Recapitulare:

  • ✅ Callbacks - funcții pasate ca argumente
  • ✅ Promises - valori viitoare cu then/catch
  • ✅ Fetch API - cereri HTTP moderne
  • ✅ Async/Await - sintaxă simplificată pentru Promises

🎯 Exerciții Bonus

🏆 Challenge 1: Convertor Callbacks → Promises

Convertește o funcție cu callback într-una care returnează Promise.

🏆 Challenge 2: Rate Limiter cu Async/Await

Implementează un rate limiter care permite maxim 3 cereri pe secundă.

🏆 Challenge 3: Retry Logic

Implementează o funcție care reîncearcă o operațiune de maxim 3 ori în caz de eșec.