Asynchronous JavaScript
JavaScript rulează într-un singur fir de execuție, dar poate gestiona operații asincrone precum timere, apeluri HTTP sau evenimente. Acest lucru permite aplicațiilor să rămână responsive și să nu blocheze interfața utilizatorului.
Exemplu: cod sincron vs. cod asincron
function executaSincron() {
document.getElementById("outputIntro").textContent = "";
document.getElementById("outputIntro").textContent += "🔹 Începe execuția sincronă\n";
for (let i = 0; i < 3; i++) {
document.getElementById("outputIntro").textContent += `🔸 Pas ${i + 1}\n`;
}
document.getElementById("outputIntro").textContent += "✅ Sfârșit sincron\n";
}
function executaAsincron() {
document.getElementById("outputIntro").textContent = "";
document.getElementById("outputIntro").textContent += "🔹 Începe execuția asincronă\n";
for (let i = 0; i < 3; i++) {
setTimeout(() => {
document.getElementById("outputIntro").textContent += `🔸 Pas ${i + 1}\n`;
if (i === 2) {
document.getElementById("outputIntro").textContent += "✅ Sfârșit asincron\n";
}
}, 1000 * (i + 1));
}
}
setTimeout și setInterval
Aceste două funcții permit execuția întârziată sau repetitivă a codului, fără să blocheze restul aplicației.
// setTimeout: execută o funcție o singură dată după un delay
function pornesteTimeout() {
document.getElementById("timeoutOutput").textContent = "⏳ Aștept 3 secunde...";
setTimeout(() => {
document.getElementById("timeoutOutput").textContent = "✅ Timeout complet!";
}, 3000);
}
// setInterval: execută o funcție repetitiv la fiecare X milisecunde
let intervalId;
let counter = 0;
function pornesteInterval() {
counter = 0;
document.getElementById("intervalOutput").textContent = "🔁 Pornit...";
intervalId = setInterval(() => {
counter++;
document.getElementById("intervalOutput").textContent = `🔄 Interval: ${counter} secunde`;
if (counter === 5) {
opresteInterval();
document.getElementById("intervalOutput").textContent += "\n⏹️ Interval oprit automat.";
}
}, 1000);
}
function opresteInterval() {
clearInterval(intervalId);
document.getElementById("intervalOutput").textContent += "\n🛑 Interval oprit manual.";
}
setTimeout
setInterval
Callbacks și „Callback Hell”
Un callback este o funcție transmisă ca argument, care va fi apelată mai târziu — de obicei după o operație asincronă. Dar când ai mai multe callback-uri înlănțuite, codul devine greu de citit și întreținut: așa-numitul „Callback Hell”.
Exemplu simplu cu callback
function afiseazaMesaj(text, callback) {
document.getElementById("callbackOutput1").textContent = "⏳ Se așteaptă...";
setTimeout(() => {
document.getElementById("callbackOutput1").textContent = text;
if (callback) callback();
}, 2000);
}
function executaCallback() {
afiseazaMesaj("✅ Mesaj afișat după 2 secunde", () => {
console.log("Callback executat!");
});
}
Exemplu cu „Callback Hell”
// Exemplu cu „Callback Hell”
function executaCallbackHell() {
const out = document.getElementById("callbackOutput2");
out.textContent = "🔹 Începe execuția...\n";
setTimeout(() => {
out.textContent += "🔸 Pas 1\n";
setTimeout(() => {
out.textContent += "🔸 Pas 2\n";
setTimeout(() => {
out.textContent += "🔸 Pas 3\n";
setTimeout(() => {
out.textContent += "✅ Gata!\n";
}, 1000);
}, 1000);
}, 1000);
}, 1000);
}
Promises și .then/.catch
O promisiune este un obiect care reprezintă o operație asincronă ce poate fi
rezolvată sau respinsă. Folosim .then() pentru succes și .catch()
pentru erori.
Exemplu: promisiune care se rezolvă
function executaPromisiune() {
document.getElementById("promiseOutput1").textContent = "⏳ Se așteaptă...";
new Promise((resolve, reject) => {
setTimeout(() => resolve("✅ Promisiune rezolvată!"), 2000);
})
.then(result => {
document.getElementById("promiseOutput1").textContent = result;
})
.catch(err => {
document.getElementById("promiseOutput1").textContent = "❌ Eroare: " + err;
});
}
Exemplu: promisiune care eșuează
function executaPromisiuneCuEroare() {
document.getElementById("promiseOutput2").textContent = "⏳ Se așteaptă...";
new Promise((resolve, reject) => {
setTimeout(() => reject("💥 Ceva n-a mers..."), 2000);
})
.then(result => {
document.getElementById("promiseOutput2").textContent = result;
})
.catch(err => {
document.getElementById("promiseOutput2").textContent = "❌ Eroare prinsă: " + err;
});
}
Async/Await Syntax
async și await sunt o sintaxă modernă pentru lucrul cu promisiuni. Ele fac codul
asincron să arate ca unul sincron, dar fără să blocheze execuția.
Exemplu: simulare de operație asincronă
async function executaAsync() {
document.getElementById("asyncOutput1").textContent = "⏳ Se așteaptă...";
const rezultat = await new Promise(resolve => {
setTimeout(() => resolve("✅ Operație completă!"), 2000);
});
document.getElementById("asyncOutput1").textContent = rezultat;
}
Exemplu: cu eroare prinsă elegant
async function executaAsyncCuEroare() {
document.getElementById("asyncOutput2").textContent = "⏳ Se încearcă...";
try {
const rezultat = await new Promise((_, reject) => {
setTimeout(() => reject("💥 Eroare simulată!"), 2000);
});
document.getElementById("asyncOutput2").textContent = rezultat;
} catch (err) {
document.getElementById("asyncOutput2").textContent = "❌ Prins elegant: " + err;
}
}
Fetch API și HTTP Requests
fetch() este o funcție nativă JavaScript care permite trimiterea de cereri HTTP către servere.
Este asincronă și returnează o promisiune.
Exemplu: obținere de date JSON
async function fetchPost() {
document.getElementById("fetchOutput1").textContent = "⏳ Se încarcă...";
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await response.json();
document.getElementById("fetchOutput1").textContent = JSON.stringify(data, null, 2);
} catch (err) {
document.getElementById("fetchOutput1").textContent = "❌ Eroare: " + err.message;
}
}
Exemplu: trimitere de date (POST)
async function sendPost() {
document.getElementById("fetchOutput2").textContent = "⏳ Se trimite...";
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
title: "Salut Ioan!",
body: "Acesta este un mesaj trimis prin Fetch.",
userId: 7
})
});
const data = await response.json();
document.getElementById("fetchOutput2").textContent = JSON.stringify(data, null, 2);
} catch (err) {
document.getElementById("fetchOutput2").textContent = "❌ Eroare: " + err.message;
}
}
Error Handling în cod asincron
În JavaScript asincron, erorile pot apărea în timpul fetch-urilor, promisiunilor sau operațiilor întârziate. Le
putem gestiona cu .catch() sau try/catch în funcții async.
Exemplu: eroare prinsă cu .catch()
function fetchCuCatch() {
document.getElementById("errorOutput1").textContent = "⏳ Se încearcă...";
fetch("https://invalid-url.typicode.com/")
.then(response => response.json())
.then(data => {
document.getElementById("errorOutput1").textContent = JSON.stringify(data);
})
.catch(err => {
document.getElementById("errorOutput1").textContent = "❌ Eroare prinsă cu .catch(): " + err.message;
});
}
Exemplu: eroare prinsă cu try/catch
async function fetchCuTryCatch() {
document.getElementById("errorOutput2").textContent = "⏳ Se încearcă...";
try {
const response = await fetch("https://invalid-url.typicode.com/");
const data = await response.json();
document.getElementById("errorOutput2").textContent = JSON.stringify(data);
} catch (err) {
document.getElementById("errorOutput2").textContent = "❌ Eroare prinsă cu try/catch: " + err.message;
}
}