- Published on
Swiftda async/await asoslari
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Swift Concurrency — Swift 5.5 (iOS 15+) da kiritilgan, asinxron kodni sinxron kodday oson yozish imkonini beruvchi tizim. Ilgari tarmoq so'rovlari, fayllarni o'qish yoki ma'lumotlar bazasi bilan ishlash uchun callback (closure) ishlatilgan — bu kod o'qib bo'lmaydigan darajada murakkablashib ketardi. async/await buni tubdan hal qiladi — asinxron kodni xuddi oddiy sinxron koddek yozish mumkin.
Concurrency nima? — Bu bir nechta ishni "bir vaqtda" bajarish tushunchasi. Masalan, ilova serverdan ma'lumot yuklab olayotgan paytda foydalanuvchi UI bilan ishlashni davom ettirishi kerak. Agar hammasi sinxron bo'lsa — ekran muzlab qoladi.
Sinxron vs Asinxron
Sinxron kod — har bir qator oldingi qator tugaguncha kutadi. Agar biror amal 3 soniya vaqt olsa, dastur 3 soniya to'xtab qoladi va UI muzlaydi. Asinxron kod esa kutish paytida boshqa ishlarni davom ettiradi — foydalanuvchi hech narsani sezmaydi.
async kalit so'zi funksiyaga qo'yiladi — "bu funksiya vaqt olishi mumkin" degan ma'noni beradi. await esa shu funksiya natijasini kutishni bildiradi, lekin bu paytda tizim boshqa ishlarni bajaradi.
// ═══════════════════════════════════════
// SINXRON — har qator navbatida, kutadi
// ═══════════════════════════════════════
func sinxronYuklash() {
print("1. Boshlanmoqda")
// Bu joy 3 soniya kutadi — HAMMASI to'xtaydi
Thread.sleep(forTimeInterval: 3)
print("2. Yuklandi") // 3 soniyadan keyin
print("3. UI yangilandi") // 3 soniyadan keyin
// Muammo: UI 3 soniya muzlaydi!
}
// ═══════════════════════════════════════
// ASINXRON — kutish paytida boshqa ishlar davom etadi
// ═══════════════════════════════════════
func asinxronYuklash() async {
print("1. Boshlanmoqda")
// await — natijani kutadi, lekin tizim boshqa ishlarni davom etadi
try? await Task.sleep(for: .seconds(3))
print("2. Yuklandi") // 3 soniyadan keyin
print("3. UI yangilandi") // 3 soniyadan keyin
// UI muzlamaydi — boshqa ishlar bajariladi
}
async funksiya yaratish
Async funksiya yaratish uchun funksiya imzosiga async kalit so'zini qo'shish kifoya. Agar funksiya xato ham tashlashi mumkin bo'lsa, async throws yoziladi. Async funksiyani chaqirish uchun ikki yo'l mavjud: boshqa async funksiya ichidan await bilan yoki sinxron joydan Task { } bloki ichidan.
// ═══════════════════════════════════════
// ODDIY ASYNC FUNKSIYA
// ═══════════════════════════════════════
// async — bu funksiya vaqt olishi mumkin degan ma'no
func foydalanuvchiniYukla(id: Int) async -> String {
// Tarmoq so'rovi simulyatsiyasi
try? await Task.sleep(for: .seconds(1))
return "Foydalanuvchi #\(id)"
}
// async throws — xato ham tashlashi mumkin
func ma'lumotYukla(url: String) async throws -> Data {
guard let url = URL(string: url) else {
throw URLError(.badURL)
}
// URLSession.shared.data — async funksiya
let (data, _) = try await URLSession.shared.data(from: url)
return data
}
// ═══════════════════════════════════════
// ASYNC FUNKSIYANI CHAQIRISH
// ═══════════════════════════════════════
// async funksiyani faqat async kontekstdan chaqirish mumkin
// 1-usul: boshqa async funksiya ichidan
func asosiyFunksiya() async {
let ism = await foydalanuvchiniYukla(id: 1)
print(ism) // "Foydalanuvchi #1"
}
// 2-usul: Task bloki ichidan (sinxron kontekstdan)
func sinxronJoy() {
Task {
let ism = await foydalanuvchiniYukla(id: 1)
print(ism)
}
// Bu yerda davom etadi — kutmaydi
print("Task yaratildi")
}
Ketma-ket va parallel bajarish
Oddiy await bilan chaqirilgan funksiyalar ketma-ket ishlaydi — biri tugaguncha keyingisi boshlanmaydi. Lekin ko'p hollarda bir-biriga bog'liq bo'lmagan so'rovlarni parallel bajarish ancha tezroq. Buning uchun async let konstruktsiyasi ishlatiladi — u asinxron vazifani darhol boshlaydi, natijani esa keyinroq await bilan olish mumkin.
// ═══════════════════════════════════════
// KETMA-KET — biri tugaguncha ikkinchisi boshlanmaydi
// ═══════════════════════════════════════
func ketmaKet() async {
let foydalanuvchi = await foydalanuvchiniYukla(id: 1) // 1 soniya
let profil = await profilniYukla(id: 1) // 1 soniya
let postlar = await postlarniYukla(userId: 1) // 1 soniya
// Jami: 3 soniya (ketma-ket)
}
// ═══════════════════════════════════════
// PARALLEL — async let bilan bir vaqtda
// ═══════════════════════════════════════
func parallel() async {
// async let — hoziroq boshlash, keyinroq natijani olish
async let foydalanuvchi = foydalanuvchiniYukla(id: 1) // boshlandi
async let profil = profilniYukla(id: 1) // boshlandi
async let postlar = postlarniYukla(userId: 1) // boshlandi
// Uchala so'rov BIR VAQTDA ishlaydi
// await — natijalarni kutish
let f = await foydalanuvchi
let p = await profil
let po = await postlar
// Jami: ~1 soniya (parallel — eng uzuni qadar)
}
func profilniYukla(id: Int) async -> String {
try? await Task.sleep(for: .seconds(1))
return "Profil #\(id)"
}
func postlarniYukla(userId: Int) async -> [String] {
try? await Task.sleep(for: .seconds(1))
return ["Post 1", "Post 2"]
}
Callback dan async/await ga o'tish
Ilgari iOS dasturlashda asinxron ish uchun completion handler (callback) ishlatilgan. Bir nechta ketma-ket asinxron so'rov kerak bo'lganda, callback ichida callback, uning ichida yana callback yozish kerak edi — bu "Callback Hell" deb ataladi. async/await bilan xuddi shu mantiq tekis, sodda va o'qish oson kodga aylanadi.
// ═══════════════════════════════════════
// ESKI USUL — Callback Hell
// ═══════════════════════════════════════
func eskiUsul() {
yukla(url: "users/1") { user in
yukla(url: "profiles/\(user.id)") { profile in
yukla(url: "posts?user=\(user.id)") { posts in
// 3 qavatli callback — o'qish qiyin!
print(user, profile, posts)
}
}
}
}
// ═══════════════════════════════════════
// YANGI USUL — async/await
// ═══════════════════════════════════════
func yangiUsul() async throws {
let user = try await yukla(url: "users/1")
let profile = try await yukla(url: "profiles/\(user.id)")
let posts = try await yukla(url: "posts?user=\(user.id)")
// Tekis, o'qish oson, xatolarni try/catch bilan ushlash
print(user, profile, posts)
}
do-try-catch bilan xatolarni ushlash
Asinxron funksiya xato tashlashi mumkin bo'lganda, try await yoziladi — try xatoni ushlash uchun, await natijani kutish uchun. do-catch bloki ichida turli xato turlarini alohida ushlash mumkin — masalan, internet yo'qligi va boshqa xatolarni ajratib ko'rsatish.
func xavfsizYuklash() async {
do {
// try await — xato bo'lishi mumkin bo'lgan asinxron chaqiruv
let data = try await ma'lumotYukla(url: "https://api.example.com/data")
print("Yuklandi: \(data.count) bayt")
} catch URLError.notConnectedToInternet {
print("Internet yo'q!")
} catch {
print("Xato: \(error.localizedDescription)")
}
}
🎯 Topshiriq
3 ta async funksiya yarating: ismYukla(), yoshYukla(), emailYukla() — har biri 1 soniya kutib String/Int qaytarsin. Avval ketma-ket chaqiring va vaqtni o'lchang. Keyin async let bilan parallel chaqiring. Farqni kuzating.