Async: Promise și await
Event loop, async/await, rulare în paralel cu Promise.all.
Actualizat
Ce înseamnă sincron și asincron
Sincron = fiecare linie așteaptă ca cea dinainte să termine. Asincron = pornești o operație lentă (request în rețea, timer, citire de fișier) și continui cu altceva; rezultatul vine mai târziu.
De ce contează: JS din browser rulează pe un singur thread — același care desenează pagina și răspunde la click-uri. Dacă ar aștepta sincron 2 secunde un request, pagina ar îngheța 2 secunde.
Event loop — cum funcționează
- Call stack — codul care rulează acum.
- Operațiile lente sunt date browserului (rețea, timere), care le face în paralel.
- Când una termină, callback-ul ei intră într-o coadă.
- Event loop-ul ia din coadă doar când stack-ul e gol.
Există două cozi, cu priorități diferite:
| Coadă | Ce intră | Prioritate |
|---|---|---|
| microtask | .then de Promise, await, queueMicrotask |
toate rulează înainte de următorul macrotask |
| macrotask | setTimeout, setInterval, evenimente, I/O |
una pe tur |
console.log(1)
setTimeout(() => console.log(4)) // macrotask
Promise.resolve().then(() => console.log(3)) // microtask
console.log(2)
// 1, 2, 3, 4Ce este un Promise
Un Promise e un obiect care reprezintă o valoare care va veni — ca un bon de comandă: încă n-ai mâncarea, dar ai ceva ce poți aștepta.
Un Promise are 3 stări:
| Stare | Înseamnă |
|---|---|
pending |
încă se lucrează |
fulfilled |
gata, are o valoare |
rejected |
a eșuat, are o eroare |
O dată ce s-a terminat (fulfilled sau rejected), starea nu se mai schimbă.
const wait = ms => new Promise(resolve => setTimeout(resolve, ms))
fetch('/api/user')
.then(res => res.json()) // rulează la succes
.then(user => render(user))
.catch(err => showError(err)) // rulează la eroare, oriunde în lanțasync / await — același lucru, scris ca sincron
async function loadUser(id) {
try {
const res = await fetch(`/api/users/${id}`) // „pune pauză” funcției până vine răspunsul
return await res.json()
} catch (error) {
return null
}
}asyncîn fața funcției → returnează mereu un Promise.await→ așteaptă un Promise fără să blocheze pagina (doar funcția curentă „stă”).- Erorile se prind cu
try/catchnormal.
.then() |
async/await |
|
|---|---|---|
| Lizibilitate | lanțuri, callback-uri | cod de sus în jos |
| Erori | .catch() |
try/catch |
| Când | pipeline-uri scurte, în afara funcțiilor async | implicit |
Secvențial vs paralel — cea mai frecventă optimizare
// ✗ secvențial — al doilea pornește după primul: 2 × timpul
const user = await getUser()
const posts = await getPosts()
// ✓ paralel — pornesc amândouă deodată
const [user, posts] = await Promise.all([getUser(), getPosts()])Folosește secvențial doar când al doilea request depinde de rezultatul primului.
Combinatorii de Promise — tipuri și când
| Metodă | Se termină când | Dacă unul eșuează | Când |
|---|---|---|---|
Promise.all |
toate reușesc | eșuează imediat | ai nevoie de toate rezultatele |
Promise.allSettled |
toate termină | nu eșuează; primești statusul fiecăruia | vrei rezultatele parțiale |
Promise.race |
primul termină (oricum) | depinde de primul | timeout |
Promise.any |
primul reușește | eșuează doar dacă toate eșuează | mai multe surse, oricare e bună |
Greșeli clasice
forEachcuasyncnu așteaptă →for...of(secvențial) sauPromise.all(arr.map(...))(paralel).- Uiți
await→ ai un Promise în loc de valoare (user.nameeundefined). - Promise fără
catch/try→unhandledrejection. awaitîn buclă când request-urile sunt independente → lent.
Pe scurt
- JS are un singur thread; operațiile lente sunt asincrone ca pagina să nu înghețe.
- Promise = valoare viitoare: pending → fulfilled / rejected.
async/await+try/catch;Promise.allpentru paralel.