Section 2/161 menit
2. Masalah yang Dipecahkan
2. Masalah yang Dipecahkan
Kombinasi Multiple Async Sources yang Verbose
Menggabungkan dua stream async tanpa library membutuhkan code yang kompleks dan rawan error.
swift
// ❌ TANPA Async Algorithms: merge dua stream manual — verbose dan rawan race
func processEvents() async {
// Tidak ada cara idiomatis untuk merge dua AsyncStream
// Harus gunakan TaskGroup dengan coordination yang kompleks
await withTaskGroup(of: AppEvent.self) { group in
group.addTask {
for await event in networkEventStream() {
return event
}
fatalError("stream ended unexpectedly")
}
group.addTask {
for await event in userActionStream() {
return event
}
fatalError("stream ended unexpectedly")
}
// Ini hanya mengambil SATU event, bukan semua event dari kedua stream
// Merge yang benar membutuhkan implementasi koordinasi sendiri
for await event in group {
handleEvent(event)
}
}
}
swift
// ✓ DENGAN Async Algorithms: merge idiomatis dalam satu baris
import AsyncAlgorithms
func processEvents() async {
let merged = merge(networkEventStream(), userActionStream())
for await event in merged {
handleEvent(event)
}
}
Debounce Input Pengguna tanpa Timer Manual
Membatasi laju pemrosesan input (seperti search field) membutuhkan DispatchWorkItem dan management timer yang rumit.
swift
// ❌ TANPA Async Algorithms: debounce dengan Timer manual
class SearchViewModel {
private var debounceWorkItem: DispatchWorkItem?
func onSearchTextChanged(_ text: String) {
debounceWorkItem?.cancel()
debounceWorkItem = DispatchWorkItem { [weak self] in
Task { await self?.performSearch(query: text) }
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: debounceWorkItem!)
// Problem: tidak thread-safe, memory management manual, cancel bisa race
}
}
swift
// ✓ DENGAN Async Algorithms: debounce type-safe, cancellation otomatis
@MainActor
class SearchViewModel: ObservableObject {
@Published var results: [SearchResult] = []
private let searchInput = AsyncChannel<String>()
init() {
Task {
let debounced = searchInput.debounce(for: .milliseconds(300))
for await query in debounced {
results = try await performSearch(query: query)
}
}
}
func onSearchTextChanged(_ text: String) async {
await searchInput.send(text)
}
}
Batching Event untuk Efisiensi Network
Mengumpulkan event yang datang cepat dan memproses dalam batch memerlukan buffer manual.
swift
// ❌ TANPA Async Algorithms: batch manual dengan timer dan array buffer
actor EventBatcher {
private var buffer: [AnalyticsEvent] = []
private var flushTimer: Timer?
func append(_ event: AnalyticsEvent) {
buffer.append(event)
if buffer.count >= 50 {
flush()
} else if flushTimer == nil {
flushTimer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { _ in
Task { await self.flush() }
}
}
}
private func flush() {
guard !buffer.isEmpty else { return }
let batch = buffer
buffer.removeAll()
flushTimer?.invalidate()
flushTimer = nil
Task { try await uploadBatch(batch) }
}
}
swift
// ✓ DENGAN Async Algorithms: chunked(by:) handles batching secara deklaratif
func startEventProcessor(stream: AsyncStream<AnalyticsEvent>) async throws {
let batched = stream.chunked(by: .repeating(every: .seconds(5)))
// Atau batch berdasarkan count DAN waktu:
let batched2 = stream.chunks(ofCount: 50)
for await batch in batched {
try await uploadBatch(Array(batch))
}
}