Section 6/161 menit

6. Operator Time-based

6. Operator Time-based

Semua operator time-based memerlukan iOS 16+ karena menggunakan Clock protocol.

debounce

Menunggu sampai tidak ada input baru selama interval tertentu sebelum meneruskan elemen. Berguna untuk search field, scroll position, dsb.

swift
// debounce: tunggu 300ms sepi sebelum proses
let searchChannel = AsyncChannel<String>()

Task {
    for await query in searchChannel.debounce(for: .milliseconds(300)) {
        // Hanya dipanggil setelah user berhenti mengetik 300ms
        let results = try await searchAPI(query: query)
        await updateResults(results)
    }
}

// Keyboard input
func onKeyPress(_ text: String) async {
    await searchChannel.send(text)  // kirim setiap keystroke
    // debounce memfilter burst input otomatis
}

throttle

Membatasi laju emisi — maksimum satu elemen per interval. Berbeda dari debounce: throttle tidak menunggu input berhenti, tapi membatasi frekuensi output.

swift
// throttle: maksimum satu update per detik
let locationUpdates = locationManager.coordinateStream()

// reducing: bagaimana menggabungkan nilai yang di-throttle
// (ambil nilai terbaru dari burst)
let throttled = locationUpdates.throttle(
    for: .seconds(1),
    reducing: { _, latest in latest }  // ambil nilai paling baru
)

for await coordinate in throttled {
    // Dipanggil maksimum sekali per detik, meski GPS update lebih sering
    await updateMapPin(at: coordinate)
}
swift
// throttle dengan reducer berbeda: ambil nilai pertama (bukan terakhir)
let firstOnly = stream.throttle(
    for: .seconds(1),
    reducing: { first, _ in first }
)

// throttle untuk counter: jumlahkan semua nilai dalam window
let summed = intStream.throttle(
    for: .seconds(1),
    reducing: { acc, new in acc + new }
)

chunked(by: .repeating(every:))

Mengumpulkan elemen dalam window waktu tertentu, lalu emit sebagai array/collection.

swift
// chunked by time: kumpulkan 5 detik, proses sekaligus
let sensorReadings = sensorStream()  // AsyncSequence<SensorReading>

for await chunk in sensorReadings.chunked(by: .repeating(every: .seconds(5))) {
    // chunk berisi semua reading dalam 5 detik terakhir
    let average = chunk.map(\.value).reduce(0, +) / Double(chunk.count)
    await recordAverageReading(average)
}

Kombinasi Time + Count

swift
// Emit chunk ketika 100 elemen ATAU 10 detik berlalu, mana yang lebih dulu
let events = eventStream()

// Gunakan race condition antara count dan duration
for await chunk in events.chunks(ofCount: 100) {
    await uploadBatch(Array(chunk))
}

// Atau dengan waktu saja:
for await chunk in events.chunked(by: .repeating(every: .seconds(10))) {
    await uploadBatch(Array(chunk))
}