Published on

Combine: Futures va Promises nima?

Authors

Oddiy @escaping va Publisher'larning farqi

Combine yaratilishidan oldin (iOS 13 gacha) Apple va ko'pchilik dasturchilar asinxron operatsiyalar (masalan, API dan ma'lumot yuklash) tugaganini bildirish uchun @escaping closure'lardan foydalanishgan:

func getData(completion: @escaping (String, Error?) -> Void) {
    // 3 soniyadan keyin javob qaytaramiz
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        completion("Yangi ma'lumot", nil)
    }
}

Bu usul yaxshi, lekin uni Combine oqimlariga (Pipelines) to'g'ridan-to'g'ri ulab bo'lmaydi. Masalan, siz ilovangizda Combine orqali bir-biriga bog'liq ko'plab .map(), .filter(), .sink() amallarini bajaryapsiz. Agar o'rtada shunday eski usuldagi funksiya chiqib qolsa nima qilasiz?

Aynan shu muammoni hal qilish uchun Future va Promise o'ylab topilgan!

Future nima?

Future – bu kelajakda qachondir faqat bitta qiymat (yoki xato) qaytarishga va'da beruvchi maxsus Publisher. Uni doimiy ravishda qiymat yuboraveradigan oddiy Publisher'lardan farqi shundaki, u bitta natija bergach ishini yakunlaydi (finished yoki failure).

import Combine

func getFuturePublisher() -> Future<String, Error> {

    // Future bitta promise (va'da) qabul qiladi
    return Future { promise in

        // Eski usuldagi funksiyani chaqiramiz
        getData { value, error in

            // Xato bo'lsa
            if let error = error {
                promise(.failure(error)) // Va'dani xatolik bilan yakunlash
            } else {
                // To'g'ri ishladi
                promise(.success(value)) // Va'dani muvaffaqiyat bilan yakunlash
            }

        }
    }
}

Nimaga bu juda zo'r?

Endi biz getFuturePublisher() orqali xuddi Combine Publisher kabi foydalanishimiz mumkin! Barcha oddiy .sink, .map, va Combine'ning maxsus filtrlarini bunga ham yopishtirish imkonini beradi:

class FutureBootcampViewModel: ObservableObject {
    @Published var title: String = "Boshlang'ich matn"
    var cancellables = Set<AnyCancellable>()

    func downloadData() {
        getFuturePublisher()
            .sink(receiveCompletion: { _ in
                // Tugadi yoki xatolik
            }, receiveValue: { [weak self] returnedValue in
                // Qaytgan natijani UI ga bog'lash
                self?.title = returnedValue
            })
            .store(in: &cancellables)
    }
}

Xulosa: Agar siz ishlayotgan loyihada yoki kutubxonada (SDK) faqat completion handler (@escaping) li funksiyalar bo'lsa, ularni Combine tarmog'iga ulay olmaysiz deb xafa bo'lmang. Future bloki orqali ularni osongina zamonaviy Publisher'ga aylantirib yuborishingiz mumkin.

Buy mea coffee