Swift Academy · Pelajaran

Menjembatani callback lama/Combine ke async/await

Bungkus handler penyelesaian menggunakan withCheckedContinuation / withCheckedThrowingContinuation , lalu jembatani publisher Combine ke AsyncSequence untuk perulangan for await sederhana.

Pelajaran 2 dari 38 langkah

Menjembatani callback lama/Combine ke async/await adalah pelajaran Swift Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 3. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Swift Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Swift Academy mencakup 3 pelajaran total.

Mengapa melakukan bridging?

Tujuan: Gunakan kontinuitas untuk membungkus callback dan perlakukan aliran Combine sebagai AsyncSequence.

  • Kontinuitas (tanpa pelemparan galat / dengan pelemparan galat)
  • Contoh bridging URLSession
  • Konsumsi Combine → for await

Kontinuasi tanpa pelemparan galat

Gunakan withCheckedContinuation ketika API lama tidak dapat gagal. Resume tepat satu kali.

// Old-style API
func fetchName(completion: @escaping (String) -> Void) {
    // simulate async
    Task { try? await Task.sleep(nanoseconds: 80_000_000); completion("Ana") }
}

// Async wrapper using continuation (non-throwing)
func fetchName() async -> String {
    await withCheckedContinuation { (cont: CheckedContinuation<String, Never>) in
        fetchName { value in cont.resume(returning: value) }
    }
}

Task {
    let name = await fetchName()
    print("name:", name) // "Ana"
}

Kontinuasi dengan pelemparan galat

Gunakan withCheckedThrowingContinuation untuk meneruskan galat API lama melalui throw. Pastikan hanya ada satu jalur resume.

enum NetError: Error { case offline; case badStatus }

func loadNumber(completion: @escaping (Result<Int, Error>) -> Void) {
    Task {
        try? await Task.sleep(nanoseconds: 80_000_000)
        completion(.failure(NetError.offline))
    }
}

func loadNumber() async throws -> Int {
    try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Int, Error>) in
        loadNumber { result in
            switch result {
            case .success(let v): cont.resume(returning: v)
            case .failure(let e): cont.resume(throwing: e)
            }
        }
    }
}

Task {
    do {
        let n = try await loadNumber()
        print(n)
    } catch {
        print("error:", error) // offline
    }
}

Bridging URLSession

Bungkus API dengan completion handler (misalnya, URLSession) untuk mendapatkan fungsi async throws yang bersih. Ingat untuk melakukan resume tepat satu kali.

import Foundation

func getText(from url: URL) async throws -> String {
    try await withCheckedThrowingContinuation { (cont: CheckedContinuation<String, Error>) in
        let task = URLSession.shared.dataTask(with: url) { data, resp, err in
            if let err = err { cont.resume(throwing: err); return }
            guard let data = data, let text = String(data: data, encoding: .utf8) else {
                cont.resume(throwing: URLError(.badServerResponse)); return
            }
            cont.resume(returning: text)
        }
        task.resume()
    }
}

// Demo (works in environments with network access)
let demoURL = URL(string: "https://example.com")!
Task {
    do { let body = try await getText(from: demoURL); print(body.prefix(15)) }
    catch { print("network error:", error) }
}

Combine sebagai AsyncSequence

Banyak publisher Combine menyediakan .values, sehingga Anda dapat melakukan for await pada setiap emisi tanpa jembatan khusus.

import Combine
import Foundation

let subject = PassthroughSubject<Int, Never>()

// Consume Combine as AsyncSequence:
Task {
    var produced: [Int] = []
    for await value in subject.values {          // Publisher.values -> AsyncSequence
        produced.append(value)
        if produced.count == 3 { break }         // stop after 3 values
    }
    print("collected:", produced)                // e.g., [1,2,3]
}

// Publish a few values
var cancellables = Set<AnyCancellable>()
Timer.publish(every: 0.05, on: .main, in: .common)
    .autoconnect()
    .prefix(3)
    .scan(0) { acc, _ in acc + 1 }
    .sink { subject.send($0) }
    .store(in: &cancellables)

Publisher → AsyncStream

Jika .values tidak tersedia, buat jembatan kecil melalui AsyncStream. Jangan lupa melakukan cancel pada langganan setelah selesai.

import Combine

// Bridge ANY Publisher to AsyncSequence using AsyncStream (simple version)
extension Publisher {
    func asAsyncStream() -> AsyncStream<Output> {
        AsyncStream { continuation in
            let cancel = self.sink(
                receiveCompletion: { _ in continuation.finish() },
                receiveValue: { value in continuation.yield(value) }
            )
            continuation.onTermination = { _ in cancel.cancel() }
        }
    }
}

// Demo:
let pub = [10, 20, 30].publisher
Task {
    var sum = 0
    for await v in pub.asAsyncStream() { sum += v }
    print("sum:", sum) // 60
}

Gunakan kontinuasi dengan pelemparan galat

Pemeriksaan singkat: Apa cara terbaik untuk menjembatani callback yang dapat gagal ke kode asinkron?

Ringkasan

Ringkasan: Bungkus callback lama dengan kontinuasi (dengan atau tanpa pelemparan galat), lalu konsumsi Combine menggunakan .values atau jembatan kecil AsyncStream. Pastikan resume hanya dilakukan sekali dan batalkan langganan saat selesai.

Gratis untuk memulai

Belajar Swift dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
122
Pelajaran
409

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Menjembatani callback lama/Combine ke async/await” gratis?

Ya — teks lengkap “Menjembatani callback lama/Combine ke async/await” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Swift Academy, upgrade ke CoddyKit PRO. Kursus Swift Academy mencakup 3 pelajaran total.

Apa yang akan aku pelajari di “Menjembatani callback lama/Combine ke async/await”?

Bungkus handler penyelesaian menggunakan withCheckedContinuation / withCheckedThrowingContinuation , lalu jembatani publisher Combine ke AsyncSequence untuk perulangan for await sederhana. Kamu berlatih Swift Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Swift Academy?

Tidak diperlukan pengalaman sebelumnya. Swift Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 3.

Berapa lama pelajaran “Menjembatani callback lama/Combine ke async/await” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Swift Academy ini?

Ya. Setiap pelajaran Swift Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Produsen/konsumen, alur, batas waktu
  2. Menjembatani callback lama/Combine ke async/await
  3. Menguji kode asinkron (XCTest)
← Kembali ke Swift Academy