Debounce vs Throttle JavaScript: Perbedaan & Contoh Mudah

Kamu membuat kolom pencarian produk. Setiap kali pengguna mengetik satu huruf, aplikasi langsung mengirim request ke server. Mengetik “laptop gaming” berarti 13 request dalam hitungan detik, padahal yang dibutuhkan hanya satu. Server jadi sibuk, hasil pencarian saling tumpang tindih, dan tampilan terasa tersendat.

Masalah seperti ini diselesaikan dengan dua teknik: debounce dan throttle. Keduanya sama-sama membatasi seberapa sering sebuah fungsi dijalankan, tetapi cara kerjanya berbeda. Memahami debounce vs throttle akan membantumu memilih teknik yang tepat untuk input pencarian, scroll, resize, hingga tombol submit.

Di artikel ini kamu akan belajar pengertian debounce vs throttle, cara membuatnya dari nol, kapan memakai yang mana, serta kesalahan yang sering terjadi.

Mengapa Debounce vs Throttle Dibutuhkan untuk Event di Browser?

Beberapa event di browser bisa terpicu puluhan sampai ratusan kali per detik. Contohnya input, scroll, resize, dan mousemove. Kalau setiap pemicu langsung menjalankan pekerjaan berat, dampaknya terasa:

  • halaman lag karena perhitungan atau manipulasi DOM dilakukan terlalu sering;
  • server menerima request berlebihan dari satu pengguna;
  • baterai perangkat cepat habis;
  • hasil request lama bisa tiba setelah request baru dan menimpa tampilan.

Debounce dan throttle bekerja di sisi klien, yaitu browser. Kalau kamu ingin membatasi request dari sisi server, pelajari juga rate limiting API di Express. Idealnya keduanya dipakai bersama.

Apa Itu Debounce?

Debounce menunda eksekusi fungsi sampai pemicunya berhenti selama waktu tertentu. Setiap kali event muncul lagi sebelum waktu habis, hitungan mundur diulang dari awal. Fungsi hanya berjalan sekali, yaitu setelah aktivitas benar-benar berhenti.

Analogi sederhananya adalah pintu lift. Pintu menunggu beberapa detik sebelum menutup. Kalau ada orang masuk, hitungan mundur dimulai lagi. Pintu baru menutup setelah tidak ada orang yang datang dalam beberapa detik.

Berikut implementasi debounce paling dasar:

function debounce(fn, delay) {
  let timerId;

  return function (...args) {
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}

Cara kerjanya: setiap pemanggilan membatalkan timer sebelumnya dengan clearTimeout, lalu membuat timer baru. Hanya pemanggilan terakhir yang sempat dijalankan.

Contoh pemakaian pada kolom pencarian:

const input = document.querySelector('#search');

async function cariProduk(keyword) {
  const res = await fetch(`/api/produk?q=${encodeURIComponent(keyword)}`);
  const data = await res.json();
  console.log(data);
}

input.addEventListener(
  'input',
  debounce((event) => cariProduk(event.target.value), 400)
);

Dengan jeda 400 milidetik, mengetik “laptop gaming” hanya memicu satu request, yaitu setelah pengguna berhenti mengetik sejenak.

Apa Itu Throttle?

Throttle membatasi fungsi agar berjalan paling banyak satu kali dalam interval tertentu, seberapa pun sering event terpicu. Berbeda dengan debounce, throttle tidak menunggu aktivitas berhenti. Fungsi tetap berjalan secara berkala selama event terus berlangsung.

Analogi sederhananya adalah bus yang berangkat setiap 10 menit. Seberapa banyak penumpang datang, bus tetap berangkat sesuai jadwal.

Implementasi throttle dasar:

function throttle(fn, interval) {
  let lastCall = 0;

  return function (...args) {
    const now = Date.now();

    if (now - lastCall >= interval) {
      lastCall = now;
      fn.apply(this, args);
    }
  };
}

Cara kerjanya: fungsi menyimpan waktu eksekusi terakhir. Panggilan baru hanya dijalankan kalau selisih waktunya sudah melewati interval.

Contoh pemakaian pada event scroll:

function perbaruiProgressBar() {
  const tinggi = document.documentElement.scrollHeight - window.innerHeight;
  const persen = (window.scrollY / tinggi) * 100;
  document.querySelector('#progress').style.width = `${persen}%`;
}

window.addEventListener('scroll', throttle(perbaruiProgressBar, 100));

Sekalipun event scroll terpicu ratusan kali, progress bar hanya diperbarui maksimal 10 kali per detik.

Debounce vs Throttle: Perbedaan Utama

Tabel berikut merangkum debounce vs throttle dari lima aspek penting, mulai dari waktu eksekusi sampai contoh kasus penggunaannya.

AspekDebounceThrottle
Kapan fungsi berjalanSetelah aktivitas berhenti selama waktu tertentuSecara berkala selama aktivitas berlangsung
Jumlah eksekusiSatu kali di akhir rangkaian eventMaksimal satu kali per interval
Jika event terus datangFungsi tidak pernah berjalanFungsi tetap berjalan sesuai interval
AnalogiPintu lift menunggu orang terakhirBus berangkat tiap beberapa menit
Cocok untukPencarian, auto-save, validasi formScroll, resize, drag, mousemove

Cara cepat memilih antara debounce vs throttle: tanyakan apakah kamu hanya peduli pada hasil akhir atau perlu pembaruan berkala. Jika hanya hasil akhir yang penting, pakai debounce. Jika perlu respons yang terus berjalan selama aktivitas berlangsung, pakai throttle.

Debounce vs Throttle: Kapan Memakai Debounce?

  • Kolom pencarian dan autocomplete. Kirim request hanya setelah pengguna berhenti mengetik.
  • Validasi form. Cek ketersediaan username atau email setelah pengguna selesai mengetik, bukan di setiap huruf.
  • Auto-save. Simpan draf setelah pengguna berhenti menulis beberapa detik.
  • Penyesuaian layout setelah resize. Hitung ulang ukuran setelah pengguna selesai menarik jendela.

Debounce vs Throttle: Kapan Memakai Throttle?

  • Event scroll. Misalnya progress bar, tombol “kembali ke atas”, atau memuat konten saat mendekati dasar halaman (infinite scroll).
  • Mousemove dan drag. Memperbarui posisi elemen atau tooltip secara berkala.
  • Game atau animasi sederhana. Membatasi frekuensi tembakan atau pembaruan input.
  • Tombol yang bisa ditekan berulang. Membatasi aksi seperti “like” agar tidak terkirim puluhan kali dalam satu detik.

Debounce vs Throttle: Opsi Leading dan Trailing Edge

Implementasi dasar di atas hanya menjalankan fungsi di akhir (trailing) untuk debounce, dan di awal (leading) untuk throttle. Pada praktiknya kamu kadang butuh perilaku berbeda.

  • Debounce leading: fungsi langsung berjalan pada pemanggilan pertama, lalu panggilan berikutnya diabaikan sampai jeda selesai. Berguna untuk tombol submit agar tidak terklik dua kali.
  • Throttle trailing: panggilan terakhir yang tertahan tetap dijalankan setelah interval selesai, sehingga keadaan akhir tidak terlewat.

Untuk kebutuhan ini, banyak developer memakai library Lodash yang menyediakan _.debounce dan _.throttle lengkap dengan opsi leading, trailing, serta metode cancel dan flush.

Kesalahan Umum dalam Debounce vs Throttle

1. Membuat Ulang Fungsi di Setiap Render

Pada React, jika kamu memanggil debounce(...) langsung di badan komponen, fungsi baru dibuat setiap render dan timer lama tidak ikut terbatalkan. Hasilnya debounce seolah tidak bekerja. Simpan fungsinya dengan useMemo, useRef, atau useCallback agar instance-nya sama antar render.

2. Lupa Membersihkan Timer

Kalau komponen dilepas saat timer masih berjalan, fungsi bisa tetap dieksekusi setelahnya. Batalkan timer saat cleanup, misalnya lewat metode cancel pada Lodash.

3. Salah Memilih Teknik

Salah pilih debounce vs throttle membuat aplikasi terasa janggal. Memakai debounce pada event scroll membuat pembaruan baru muncul setelah pengguna berhenti scroll. Efeknya terasa kaku. Sebaliknya, throttle pada kolom pencarian tetap mengirim beberapa request di tengah proses mengetik.

4. Menganggap Debounce Menyelesaikan Semua Masalah Request

Debounce mengurangi jumlah request, tetapi tidak menjamin urutan respons. Respons lama masih bisa tiba setelah respons baru. Gunakan AbortController untuk membatalkan request sebelumnya.

5. Memakai Jeda yang Terlalu Panjang atau Terlalu Pendek

Jeda terlalu panjang membuat aplikasi terasa lambat merespons. Jeda terlalu pendek membuat debounce tidak banyak berguna. Untuk kolom pencarian, titik awal yang umum adalah sekitar 300 sampai 500 milidetik, lalu sesuaikan dengan hasil uji pada aplikasimu.

Alternatif untuk Kasus Visual

Untuk pembaruan yang terkait tampilan, seperti animasi saat scroll atau drag, requestAnimationFrame sering menjadi pilihan lebih halus karena sinkron dengan frekuensi refresh layar. Kamu bisa mengombinasikannya dengan throttle bila perlu membatasi pekerjaan yang lebih berat.

Pertanyaan yang Sering Diajukan (FAQ)

Apa perbedaan debounce vs throttle?

Debounce menjalankan fungsi sekali setelah aktivitas berhenti selama waktu tertentu. Throttle menjalankan fungsi secara berkala, maksimal satu kali per interval, selama aktivitas berlangsung.

Debounce vs throttle, mana yang lebih baik?

Keduanya bukan saling menggantikan. Debounce cocok untuk kasus yang hanya membutuhkan hasil akhir, seperti pencarian. Throttle cocok untuk kasus yang membutuhkan pembaruan berkala, seperti scroll.

Apakah konsep debounce vs throttle hanya ada di JavaScript?

Konsepnya umum dan dipakai di banyak bahasa dan framework. Artikel ini membahas penerapannya di JavaScript karena paling sering dipakai pada event di browser.

Perlu library atau cukup menulis sendiri?

Untuk kebutuhan sederhana, versi buatan sendiri di artikel ini sudah cukup. Jika kamu butuh opsi lanjutan seperti leading, trailing, dan cancel, library seperti Lodash lebih praktis dan teruji.

Apakah debounce cocok untuk tombol submit?

Bisa, terutama dengan opsi leading agar klik pertama langsung diproses dan klik berikutnya diabaikan. Tetap tambahkan perlindungan di sisi server, misalnya dengan pembatasan request, karena pembatasan di browser mudah dilewati.

Kesimpulan

Debounce vs throttle adalah dua cara mengendalikan seberapa sering fungsi dijalankan. Debounce menunggu aktivitas berhenti lalu menjalankan fungsi sekali, cocok untuk pencarian, validasi form, dan auto-save. Throttle menjalankan fungsi secara berkala, cocok untuk scroll, resize, dan mousemove.

Coba praktikkan debounce vs throttle dengan membuat kolom pencarian yang memakai debounce dan progress bar scroll yang memakai throttle. Setelah itu, bandingkan jumlah pemanggilan fungsi di console. Perbedaannya akan langsung terlihat.

Belum paham bagian tertentu atau punya contoh kasus sendiri? Tulis di kolom komentar, kita diskusikan bersama.

Leave a Reply

Your email address will not be published. Required fields are marked *