Async/Await — asoslar
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:
getUserfunksiyasini boshlaydi- U Promise qaytarganini ko'radi
- Funksiyadan vaqtincha chiqadi — boshqa kod ishlashi mumkin
- 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