- Published on
Async Let yordamida kodlarni parallel ishlash
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Asinxron kodlarning ketma-ketlik muammosi
O'tgan darslarda ko'rganimizdek, agar bitta Task ichida bir nechta await chaqiruvlari ketma-ket yozilsa, ular birin-ketin (sinxrondek) ishlaydi. Ya'ni birinchi amal butunlay tugamagunicha, ikkinchi amal boshlanmaydi.
Tasavvur qiling, biz internetdan 4 xil rasmni yuklab olmoqchimiz:
Task {
do {
// Har biri 2 soniyadan vaqt oladi deylik. Jami: 8 soniya kutiladi.
let image1 = try await fetchImage()
let image2 = try await fetchImage()
let image3 = try await fetchImage()
let image4 = try await fetchImage()
self.images.append(contentsOf: [image1, image2, image3, image4])
} catch { ... }
}
Albatta, 4 ta rasmni alohida-alohida Task qilib ochish mumkin, lekin bunday qilsak kodimiz juda xunuklashadi va agar ekrandan chiqib ketsak bu Tasklarni bitta-bitta to'xtatib (cancel qilib) chiqishimiz kerak bo'ladi. Xo'sh, bitta Task ichida bu jarayonni qanday qilib baravariga (parallel) bajarish mumkin?
Async Let — Parallellik yechimi
Swift bizga async let degan ajoyib xususiyatni taqdim etadi. Bu xususiyat asinxron funksiyani kutmasdan darhol boshlab yuborish imkonini beradi. Natijani esa kerak bo'lganda birgalikda kutib olamiz.
Task {
do {
// Bu kodlar funksiyani darhol ishga tushiradi, lekin natijasini kutib o'tirmaydi!
async let fetchImage1 = fetchImage()
async let fetchImage2 = fetchImage()
async let fetchImage3 = fetchImage()
async let fetchImage4 = fetchImage()
// Hamma funksiyalar allaqachon bir vaqtda (parallel) ishni boshlagan.
// Endi biz ularning barchasi tayyor bo'lishini bitta qatorda kutib (await) olamiz:
let (image1, image2, image3, image4) = await (try fetchImage1, try fetchImage2, try fetchImage3, try fetchImage4)
// Agar har bir rasm yuklanishi 2 soniyadan olsa, endi jami operatsiya atigi 2 soniya davom etadi!
self.images.append(contentsOf: [image1, image2, image3, image4])
} catch {
print("Xatolik: \(error)")
}
}
Muhim qoidalar va afzalliklari
- Xatolar (Errors): Yuqoridagi misolda funksiya xato (error) qaytarishi mumkin bo'lganligi sababli biz guruh ichida ham
tryso'zidan foydalandik. Esda tuting: Agar shu to'rtta rasmning bittasida xatolik chiqsa (tryqulasa), butun guruh bekor qilinadi va kod darholcatchblokiga tushib ketadi. Bunga yo'l qo'ymaslik uchun, ma'lumot tushib qolishi mumkin bo'lgan qismlardatry?ishlating. - Bir xil bo'lishi shart emas:
async letbilan turli xil qiymat qaytaruvchi mutlaqo boshqa-boshqa funksiyalarni ham birga chaqirish mumkin.
Masalan:
async let fetchImage1 = fetchImage() // UIImage qaytaradi (throws qiladi)
async let fetchTitle1 = fetchTitle() // String qaytaradi (throws qilmaydi)
// E'tibor bering, fetchTitle throws qilmagani uchun, uning oldida try shart emas.
let (image, title) = await (try fetchImage1, fetchTitle1)
Qachon async let ishlatmaslik kerak?
async let barmoq bilan sanarli (masalan 3-4 ta) so'rovlarni bir vaqtda bajarish uchun ideal vositadir. Ya'ni, profil sahifasiga kirganda 1 marta foydalanuvchi ma'lumoti, 1 marta uning do'stlari ro'yxati va 1 marta rasmini paralel chaqirish kerak bo'lsa — bu ayni muddao.
Biroq, agar sizda array ko'rinishidagi 50 ta rasm bo'lsa va siz ularning hammasini bitta-bitta paralel yuklamoqchi bo'lsangiz, uni bunday yozib bo'lmaydi: async let image50 = fetchImage50()
Buning uchun yanada kuchliroq bo'lgan TaskGroup tushunchasi mavjud. U haqida keyingi darsimizda gaplashamiz.