Learning
JavaScript

Aszinkron JavaScript és Event Loop

Callback, Promise, async/await és az event loop – hogyan működik az aszinkron JavaScript a motor alatt.

Aszinkron JavaScript és Event Loop

Ez az oldal a teljes jegyzet 12–13. fejezetét foglalja össze: aszinkron minták (callback, Promise, async/await) és az event loop működése.
Forrás: content/javascript/javascript-full.mdx.


1. Miért kell az aszinkronitás?

A JavaScript single‑threaded – egyszerre egy dolgot csinál. Ha egy hosszú művelet (pl. hálózati kérés) blokkolná a fő szálat, a teljes UI "megfagyna".

Aszinkron kóddal:

  • a hosszú művelet külön környezetben fut (Web APIs / Node APIs),
  • amikor elkészül, egy queue‑ba kerül,
  • az event loop a fő szál felszabadulása után futtatja a callbacket.

2. Callback – a klasszikus megközelítés

function adatLetoltes(callback) {
  setTimeout(() => {
    const adat = { nev: "Adam" };
    callback(adat);
  }, 1000);
}

adatLetoltes(function(adat) {
  console.log(adat.nev); // "Adam" – 1 mp múlva
});

Callback hell probléma:

felhasznaloLetolt(id, function(user) {
  profilLetolt(user.profilId, function(profil) {
    kepLetolt(profil.kepId, function(kep) {
      console.log(kep); // 3 szint mélyen
    });
  });
});

Nehéz olvasni, nehéz hibát kezelni → ezért jött a Promise.


3. Promise – modern alap

Promise = egy jövőbeli érték ígérete:

  • pending → folyamatban,
  • fulfilled → sikeres,
  • rejected → hiba.
const igerem = new Promise((resolve, reject) => {
  setTimeout(() => {
    const siker = true;
    if (siker) {
      resolve({ nev: "Adam" });
    } else {
      reject(new Error("Valami hiba történt"));
    }
  }, 1000);
});

igerem
  .then(adat => console.log(adat.nev))
  .catch(hiba => console.error(hiba))
  .finally(() => console.log("Kész"));

Promise láncolás:

felhasznaloLetolt(id)
  .then(user => profilLetolt(user.profilId))
  .then(profil => kepLetolt(profil.kepId))
  .then(kep => console.log(kep))
  .catch(hiba => console.error(hiba));

4. async / await – szinkronszerű szintaxis

async/await csak cukor a Promise‑okra, de sokkal olvashatóbb:

async function adatokLekeres(id) {
  try {
    const user = await felhasznaloLetolt(id);
    const profil = await profilLetolt(user.profilId);
    const kep = await kepLetolt(profil.kepId);
    console.log(kep);
  } catch (hiba) {
    console.error("Hiba:", hiba);
  }
}

adatokLekeres(123);

Fontos:

  • async függvény mindig Promise‑t ad vissza,
  • await csak async függvényben használható,
  • try/catch fogja a Promise‑ok reject ágát.

Párhuzamos futtatás – Promise.all

async function parhuzamos() {
  // Lassú – sorban fut
  const a = await lekerA();
  const b = await lekerB();

  // Gyorsabb – párhuzamosan indul
  const [a2, b2] = await Promise.all([lekerA(), lekerB()]);
}

5. fetch – hálózati kérések

async function felhasznalokLeker() {
  try {
    const valasz = await fetch("https://api.example.com/users");

    if (!valasz.ok) {
      throw new Error(`HTTP hiba: ${valasz.status}`);
    }

    const adatok = await valasz.json();
    return adatok;
  } catch (hiba) {
    console.error("Hálózati hiba:", hiba);
    throw hiba;
  }
}

Minta: fetchres.ok ellenőrzés → res.json()try/catch.


6. Event Loop – hogyan ütemeződik minden?

Fő szereplők

  • Call Stack – szinkron kód futtatása (LIFO verem).
  • Web APIs / Node APIs – környezet specifikus aszinkron műveletek (setTimeout, fetch, DOM eventek).
  • Task Queue (Macrotask Queue) – pl. setTimeout, setInterval, DOM event callbackek.
  • Microtask Queue – Promise callbackek (.then, .catch, .finally, queueMicrotask).

Prioritás: Call Stack → Microtask Queue → Task Queue.


Klasszikus példakód

console.log("1");

setTimeout(() => {
  console.log("2");
}, 0);

Promise.resolve().then(() => {
  console.log("3");
});

console.log("4");

Kimenet: 1, 4, 3, 2

Miért?

  1. console.log("1") – azonnal fut → "1"
  2. setTimeout callback megy a Web APIs‑ba, majd 0 ms után a Task Queue‑ba.
  3. Promise.resolve().then(...) callback a Microtask Queue‑ba kerül.
  4. console.log("4") – azonnal fut → "4"
  5. Call Stack kiürül → event loop:
    • először a Microtask Queue összes elemét futtatja → "3",
    • ezután jön a Task Queue → "2".

Mikro vs makrotask

setTimeout(() => console.log("setTimeout"), 0);

Promise.resolve().then(() => console.log("Promise"));

Kimenet:
Promise
setTimeout

Szabály: minden render / stack kiürülés után előbb kerülnek lefuttatásra a microtaskok (Promise callbackek), csak utána a macrotaskok (pl. setTimeout).


Összefoglaló – Aszinkron JS + Event Loop

  • Callback: egyszerű, de callback hell‑hez vezethet.
  • Promise: láncolható, olvashatóbb, mint callbackek.
  • async/await: a Promise‑okra épül, de szinkron stílusú kódot ad.
  • Event loop:
    • JS single‑threaded, de a környezet (böngésző/Node) segít az aszinkronitásban,
    • Microtask Queue (Promise) prioritást élvez a Task Queue (setTimeout) előtt.

Következő oldal:
DOM, böngésző API-k és hibakezelés →

On this page