Async/Await — asoslar

~20 daq · JavaScript · Asinxron JavaScript

Muammodan boshlaylik

Promise zanjiri Callback Hell dan ancha yaxshi. Lekin o'z muammolari bor.

Tasavvur qiling: foydalanuvchi ma'lumoti olindi, undan user.id kerak. Keyin postlar olindi, ulardan posts[0].id kerak. Keyin izohlar olindi. Ularni bir joyda ko'rsatish kerak — lekin user va posts kechroq kerak bo'ladigan .then() da ko'rinmaydi:

getUser(id)
  .then(function(user) {
    return getPosts(user.id);
    // user bu yerda bor
  })
  .then(function(posts) {
    // user bu yerda YO'Q — yuqorida qoldi
    return getComments(posts[0].id);
  })
  .then(function(comments) {
    // user ham yo'q, posts ham yo'q
    render(???, ???, comments); // ❌ qanday ko'rsatamiz?
  });

Yechim — ichma-ich joylashtirish yoki o'zgaruvchilarni tashqarida e'lon qilish. Ikkalasi ham noqulay.

Async/Await — bu muammoni yo'q qiladi. Asinxron kodni sinxron ko'rinishda yozish imkonini beradi.


async/await nima?

async/await — Promise ning yangi yozuv usuli. Mexanizm o'zgarmaydi: Promise hali ham bor, Event Loop hali ham bor. Faqat yozish qulaylashdi.

Hayotiy o'xshatma

Vazifa ro'yxati bilan ishlash. Eski usul: "birinchi vazifani tugatsang, ikkinchisini boshla, u tugasach uchinchisini..." — har biri boshqasining ichida. Yangi usul: "birinchi, keyin ikkinchi, keyin uchinchi" — ketma-ket, oddiy ro'yxat.

Async/Await — asinxron ishlarni xuddi shunday, ketma-ket ro'yxat ko'rinishida yozishga imkon beradi. JavaScript esa o'zi hamma narsani to'g'ri bajaradi.


async funksiya

async kalit so'zi funksiya oldiga yoziladi. Bu funksiya doimo Promise qaytaradi.

async function salomlash() {
  return "Salom!";
}

Bu funksiya "Salom!" qaytaradi — lekin aslida Promise.resolve("Salom!") qaytaradi. Tashqaridan foydalanganda .then() bilan ishlash mumkin, yoki boshqa async funksiyada await bilan.


await — kutish

await — faqat async funksiya ichida yoziladi. Promise yoniga qo'yilganda — u tugaguncha kutadi va natijani o'zgaruvchiga yozadi.

async function foydalanuvchiOlish(id) {
  const foydalanuvchi = await getUser(id);
  // getUser tugamaguncha keyingi qator boshlanmaydi
  // tugagandan keyin — natija foydalanuvchi o'zgaruvchisida

  const postlar = await getPosts(foydalanuvchi.id);
  // foydalanuvchi bu yerda bor — `await` tufayli yuqorida kutilgan

  const izohlar = await getComments(postlar[0].id);
  // postlar ham bor

  render(foydalanuvchi, postlar, izohlar); // ← uchala bor ✅
}

Oldingi muammo yo'qoldi. foydalanuvchi va postlar barcha keyingi qatorlarda mavjud — chunki await ularni kutib olgan.

Nima uchun bu sinxron ko'rinsa ham asinxron?

await — JavaScript ni to'sib qo'ymaydi. await getUser(id) deyilganda, JavaScript:

  1. getUser funksiyasini boshlaydi
  2. U Promise qaytarganini ko'radi
  3. Funksiyadan vaqtincha chiqadi — boshqa kod ishlashi mumkin
  4. Promise tugagach — funksiyaga qaytadi va davom etadi

Event Loop to'silmaydi. Faqat bu async funksiya kutadi — qolgan hammasi ishlayveradi.


Xatolarni ushlash — try/catch

Promise zanjirida xatolar .catch() bilan ushlanardi. Async/Await da — oddiy try/catch:

async function yukla(id) {
  try {
    const foydalanuvchi = await getUser(id);
    const postlar       = await getPosts(foydalanuvchi.id);
    render(foydalanuvchi, postlar);
  } catch (xato) {
    // Yuqoridagi istalgan qatorda xato chiqsa — shu yerga tushadi
    console.error("Yuklanishda xato:", xato.message);
  }
}

Callback Hell da har qadamda if (xato) return;. Promise da bitta .catch(). Async/Await da bitta try/catch. Xato boshqaruvi tobora soddalashib bordi.


async/await va Promise — bir xil narsa

Async/Await — Promise ning boshqa yozuv usuli, yangi narsa emas.

// Promise bilan
function yukla(id) {
  return getUser(id)
    .then(function(user) {
      return getPosts(user.id);
    })
    .then(function(posts) {
      return render(posts);
    });
}

// Async/Await bilan — bir xil narsa, boshqacha yozuv
async function yukla(id) {
  const user  = await getUser(id);
  const posts = await getPosts(user.id);
  return render(posts);
}

Ikkala funksiya ham Promise qaytaradi. Ikkisi ham bir xil ishlaydi. Faqat ikkinchisi o'qishga osonroq.


Tez-tez uchraydigan xatolar

await ni async siz ishlatish:

await faqat async funksiya ichida ishlaydi. Tashqarida yozilsa — sintaksis xatosi.

// ❌
function oddiy() {
  const data = await fetch("/api"); // SyntaxError
}

// ✅
async function toGri() {
  const data = await fetch("/api");
}

await ni unutish:

await yozilmasa — natija o'rniga Promise o'zgaruvchiga yoziladi.

async function test() {
  const res = fetch("/api"); // ❌ await yo'q — res = Promise, javob emas
  console.log(res);          // Promise {<pending>}

  const res2 = await fetch("/api"); // ✅
  console.log(res2);                // Response {...}
}

Bu xatoni topish qiyin — kod xato bermaydi, faqat noto'g'ri ishlaydi.

forEach bilan async — ishlamaydi:

forEach — callback berganingizni kutmaydi. Async callback bersangiz ham — forEach natijasini kutmaydi.

// ❌ — forEach async callbackni kutmaydi
[1, 2, 3].forEach(async function(id) {
  const user = await getUser(id);
  console.log(user); // chiqadi, lekin tartibsiz va "tugadi" undan keyin
});
console.log("tugadi"); // ← bu avval chiqadi!

// ✅ — for...of kutadi
for (const id of [1, 2, 3]) {
  const user = await getUser(id);
  console.log(user);
}
console.log("tugadi"); // ← haqiqatda oxirida

Xulosa

async — funksiya oldiga yoziladi. Bu funksiya doimo Promise qaytaradi.

await — Promise yoniga yoziladi, faqat async ichida. Promise tugaguncha kutadi, natijani qaytaradi.

Async/Await — Promise ning qulay yozuv usuli. Mexanizm o'zgarmaydi. Asinxron kod sinxron ko'rinishda yoziladi — o'qish va xato topish osonlashadi.

Callback Hell → Promise → Async/Await. Har biri avvalgisining muammosini yechdi.


Keyingi dars

40-dars: Async/Await — xatolarni ushlash, parallel va ketma-ket bajarish