Mengapa browser melakukan throttling pada timer JavaScript
(nolanlawson.com)- Dalam JavaScript,
setTimeout(0)sebenarnya tidak langsung dijalankan dan sering mengalami penundaan minimum 4ms, yang merupakan batasan bawaan browser untuk mencegah penyalahgunaan - Batasan ini diterapkan untuk mencegah situs web menyalahgunakan timer secara berlebihan hingga menyebabkan boros baterai atau penurunan interaksi; dalam mode baterai batas ini bisa diperketat menjadi 16ms, dan di tab latar belakang menjadi 1 detik
- Para developer telah memanfaatkan berbagai API timer alternatif seperti
setImmediate,MessageChannel.postMessage,window.postMessage, danscheduler.postTaskuntuk mengakali keterbatasansetTimeout - Hasil benchmark nyata menunjukkan bahwa Chrome dan Firefox menerapkan clamping 4ms, tetapi
MessageChanneldanscheduler.postTaskberjalan hampir tanpa jeda, sementara Safari cenderung membatasisetTimeoutlebih agresif - Pada dasarnya ini adalah persoalan keseimbangan antara perlindungan pengalaman pengguna dan kebebasan developer; saat ini Scheduler API mulai menjadi solusi standar, tetapi jika penyalahgunaan terjadi, intervensi browser baru juga bisa diperkenalkan
Latar belakang pembatasan setTimeout
- Bahkan untuk
setTimeout(0), penyalahgunaan membuat eksekusi nyata sering baru terjadi setidaknya 4ms kemudianconst start = performance.now() setTimeout(() => { // dijalankan sekitar 4ms kemudian console.log(performance.now() - start) }, 0) - Ini dimaksudkan untuk mencegah pemanggilan berulang tanpa kendali, sehingga mengurangi konsumsi baterai dan keterlambatan rendering
- Beberapa browser memperketat batas ini tergantung situasi
- Mode baterai: 16ms di Edge lama
- Tab latar belakang: tertunda hingga 1 detik di Chrome
Munculnya API timer lain
setImmediate: hanya didukung di IE dan Edge lama, praktis sudah usangMessageChannel.postMessage: mengirim tugas ke event loop melalui kanal terpisahwindow.postMessage: performanya bagus, tetapi berisiko bentrok dengan skrip lainscheduler.postTask: didukung browser modern dan dinilai sebagai pilihan paling stabil
Hasil benchmark (MacBook Pro 2021, pengukuran 101 kali)
- Chrome 139:
setTimeout4.2ms,scheduler.postTask0ms - Firefox 142:
setTimeout4.72ms,scheduler.postTask0.01ms - Safari 18.4:
setTimeout26.73ms,MessageChannel0.52ms,window.postMessage0.05ms
Kasus fake-indexeddb
- IndexedDB menginginkan auto-commit transaksi tepat setelah microtask pada event loop selesai
setImmediatedi Node.js ideal untuk ini, tetapi di browsersetTimeouttidak efisien- Di Chrome, pekerjaan yang memakan 300ms di Node.js bisa membengkak menjadi 4.8 detik di browser
- Sebagai solusi,
scheduler.postTaskdigunakan sebagai default, denganMessageChannel/window.postMessagesebagai fallback demi kompatibilitas
Perdebatan soal intervensi browser
- Satu pihak berpendapat timer harus dibatasi agar developer terlindungi dari kesalahannya sendiri
- Pihak lain berpendapat kebebasan harus dijamin agar developer bisa mengukur dan mengoptimalkan sendiri
- Pada akhirnya, dengan prinsip mengutamakan pengguna, browser melakukan intervensi untuk mencegah penyalahgunaan
- Scheduler API dirancang sebagai kompromi antara kedua posisi itu, memberi developer kendali tugas yang lebih rinci sambil tetap selaras dengan pipeline rendering browser
Prospek ke depan
postTaskdanpostMessagetampaknya akan tetap dipertahankan tanpa throttling untuk sementara waktu- Namun, jika prioritas tinggi seperti
user-blockingdisalahgunakan, intervensi bisa kembali terjadi - Dalam jangka panjang, mungkin akan dibutuhkan API alternatif lain seperti
scheduler2
Belum ada komentar.