- Published on
TaskGroup orqali ommaviy asinxron ishlarni bajarish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Nega TaskGroup kerak?
Oldingi darsda biz 4 ta rasmni async let orqali bir vaqtda yuklashni o'rgangan edik. Lekin haqiqiy ilovalarda (masalan ijtimoiy tarmoq tasmalarida) bizda yuzlab postlar yoki rasmlar bo'lishi mumkin. Agar massiv (array) ichida 50 ta element bo'lsa va biz ularning barchasini o'sha vaqtning o'zida paralel yuklamoqchi bo'lsak, async let bilan buni qilish ilojsiz yoki kodi juda xunuk bo'ladi.
Shunday katta hajm va moslashuvchanlik (scalability) talab qilinganda biz TaskGroup'dan foydalanamiz.
TaskGroup turlari
Swift bizga asosan 2 xil TaskGroup turini taklif etadi:
withTaskGroup- Ichidagi vazifalar hech qanday xatolik (error) qaytarmaydigan bo'lsa.withThrowingTaskGroup- Ichidagi funksiyalardan ba'zilarithroworqali xatolik qaytarishi mumkin bo'lsa. Biz serverdan ma'lumot yuklayotganimiz uchun doimo asosan shundan foydalanamiz.
Kod namunasi: Rasm yuklovchi guruh
Endi tasavvur qiling, bizga bitta emas, o'nlab url manzillar massivi [String] berilgan. Barchasini birdaniga parallel yuklab, ularni rasmlar massiviga [UIImage] aylantiruvchi funksiya yozamiz.
func fetchImagesWithTaskGroup(urlStrings: [String]) async throws -> [UIImage] {
// Biz `withThrowingTaskGroup` ni ochyapmiz, u guruhdan nima qaytishini so'raydi. (UIImage?)
return try await withThrowingTaskGroup(of: UIImage?.self) { group in
var images: [UIImage] = []
// 🔥 Kichik samaradorlik (performance) siri:
// Kompilyator qancha element qo'shilishini oldindan bilmasligi sababli, unga xotiradan
// qancha joy ajratishni (reserve) buyuramiz.
images.reserveCapacity(urlStrings.count)
// 1-qadam: Bizdagi barcha URL larni aylanamiz va guruhga VAZIFA (Task) qo'shamiz
for urlString in urlStrings {
group.addTask {
// Bu kod parallel tarzda hamma url'lar uchun birdaniga ishga tushib ketadi
// try o'rniga try? ishlatilishi juda MUHIM!
try? await self.fetchImage(urlString: urlString)
}
}
// 2-qadam: Asinxron sikl (loop) yordamida barcha natijalarning qaytishini kutib,
// bo'sh array (images) ga qo'shib boramiz
for try await taskResult in group {
if let image = taskResult {
images.append(image)
}
}
// Hamma natija kelib bo'lgandan so'ng qaytarib yuboramiz
return images
}
}
Muhim Jiharlar
try?ning qutqaruvchi roli:withThrowingTaskGroupning eng nozik nuqtasi bor. Agar siz 50 ta rasmni yuklashni boshlasangiz va ulardan atigi 1 tasi xato (Error) bilan tugasa (va bu yernitry?emastrybilan yozgan bo'lsangiz), butun guruh xato deb qabul qilinadi va barcha to'g'ri ishlagan yuklanishlar ham bekor qilinadi. Bunga yo'l qo'ymaslik uchun vazifalarning natijasini xavfsizroq (try?orqali optional qilib) belgiladik va qulab tushmaslik kafolatini oldik.- Tartibsiz qaytish: Yuqoridagi loop ichidagi qismda (
for try await taskResult in group) e'tibor bergan bo'lsangiz, kutish asinxrondir. Qaysi rasm birinchi yuklanib bo'lsa, xuddi o'sha tartibda array ga kiradi. Ular aynan birinchi url birinchi bo'lib qaytadi degan kafolat yo'q (serverning javobiga bog'liq). - Meros (Inheritance): Siz qo'shgan har bir
addTaskota vazifaning (Parent Task) barcha xususiyatlarini va ustuvorligini (priority) meros qilib oladi. Bu tizim resurslarini isrof qilmasligini ta'minlaydi.
Xulosa
- Kichik, faqat 2-3 ta so'rov qilinayotgan hollarda kod yozilishini osonlashtirish uchun
async letmukammal tanlov. - Lekin bir turdagi yuzlab massiv qiymatlarni tez va samarali ishlash kerak bo'lsa, unda faqat va faqat
TaskGroupishlatish tavsiya qilinadi! U ilovangiz tezligini bir necha barobarga oshirishi tayin.