Cara Mengatasi Resize Event Terlalu Sering Javascript Biar Resize Halus

Cara mengatasi resize event terlalu sering javascript adalah membungkus handler dengan debounce 150-200ms untuk perhitungan akhir, atau throttle dengan requestAnimationFrame untuk update visual. Browser menembakkan resize puluhan kali selama pengguna drag jendela, jadi kode yang membaca layout di setiap tembakan langsung membuat halaman patah-patah.

Kenapa Resize Event Menembak Terlalu Sering di Browser

Event resize di objek window bersifat kontinu. Ia menyala selama ukuran viewport berubah, bukan sekali saat drag selesai. Masalahnya muncul karena developer menaruh pekerjaan berat di dalamnya.

Setiap pemanggilan offsetWidth, getBoundingClientRect, manipulasi DOM, atau fetch ikut diulang puluhan kali per detik. Main thread penuh, frame terlewat, animasi tersendat.

Kondisi Penyebab Solusi
Layout lag saat drag Baca tulis DOM tiap event Pakai throttle plus requestAnimationFrame
Fungsi API terpanggil berkali-kali Tidak ada jeda akhir resize Pakai debounce 150-200ms
Memori naik setelah pindah halaman Listener tidak dilepas Simpan referensi lalu removeEventListener

Cara Memperbaiki dengan Debounce dan Throttle

Ikuti urutan ini agar perbaikan tepat sasaran:

  1. Pindahkan semua hitung layout ke fungsi terpisah, misalnya updateLayout().
  2. Bungkus fungsi akhir seperti hitung kolom atau muat ulang data dengan debounce 150-200ms.
  3. Pakai throttle atau requestAnimationFrame khusus untuk update visual seperti posisi canvas atau lebar menu.
  4. Uji dengan drag cepat dan lambat di DevTools untuk melihat jumlah pemanggilan.
function debounce(fn, delay = 180) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

function throttle(fn, limit = 100) {
  let waiting = false;
  return function (...args) {
    if (waiting) return;
    waiting = true;
    setTimeout(() => {
      fn.apply(this, args);
      waiting = false;
    }, limit);
  };
}

const hitungAkhir = debounce(() => {
  updateLayout();
}, 180);

const updateVisual = throttle(() => {
  requestAnimationFrame(updateLayout);
}, 100);

window.addEventListener("resize", hitungAkhir);
window.addEventListener("resize", updateVisual);

Pilih debounce untuk pekerjaan yang cukup jalan sekali setelah resize berhenti. Pilih throttle untuk pekerjaan yang harus terlihat bergerak selama resize, seperti menggambar ulang grafik.

Cara Mencegah Layout Patah dan Listener Bocor

Handler anonim tidak bisa dihapus. Simpan dalam variabel agar removeEventListener menemukan fungsi yang sama. Cache juga ukuran elemen di variabel, jangan panggil clientWidth berulang di loop.

  • Lepas listener saat komponen tidak dipakai, terutama di single page app.
  • Hindari pola baca layout lalu tulis style secara bergantian dalam satu handler.
  • Gunakan ResizeObserver untuk memantau satu elemen spesifik, bukan seluruh window.
  • Pisahkan hitung data berat dari render agar frame tetap 60fps.

FAQ

Apakah debounce selalu lebih baik untuk resize?

Tidak, debounce hanya ideal untuk hitung akhir setelah pengguna berhenti mengubah ukuran.

Kapan throttle lebih cocok daripada debounce?

Throttle lebih cocok saat tampilan harus diperbarui terus selama drag, seperti canvas atau sidebar.

Apakah perlu menghapus listener resize?

Ya, hapus dengan removeEventListener memakai referensi fungsi yang sama agar tidak terjadi kebocoran memori.