Saya tertarik dengan fungsi "debouncing" dalam javascript, yang ditulis di sini: http://davidwalsh.name/javascript-debounce-function
Sayangnya kode ini tidak dijelaskan dengan cukup jelas untuk saya mengerti. Adakah yang bisa membantu saya mencari tahu cara kerjanya (saya meninggalkan komentar saya di bawah). Singkatnya saya hanya benar-benar tidak mengerti cara kerjanya
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
EDIT: Cuplikan kode yang disalin sebelumnya ada callNow
di tempat yang salah.
javascript
debouncing
Startec
sumber
sumber
clearTimeout
dengan sesuatu yang bukan ID penghitung waktu yang valid, ia tidak melakukan apa-apa.WindowTimers
objek di mana metode itu dipanggil, metode tidak melakukan apa-apa."Jawaban:
Kode dalam pertanyaan sedikit diubah dari kode di tautan. Di tautan, ada tanda centang
(immediate && !timeout)
SEBELUM membuat batas waktu baru. Setelah itu menyebabkan mode langsung tidak pernah menyala. Saya telah memperbarui jawaban saya untuk membubuhi keterangan versi yang berfungsi dari tautan.sumber
immediate && timeout
cek. Tidak akan selalu adatimeout
(karenatimeout
disebut sebelumnya). Juga, apa gunanyaclearTimeout(timeout)
, ketika dideklarasikan (menjadikannya tidak terdefinisi) dan dihapus, sebelumnyaimmediate && !timeout
check adalah ketika menghilangkan bounce dikonfigurasi denganimmediate
bendera. Ini akan menjalankan fungsi segera tetapi memaksakanwait
batas waktu sebelumnya jika dapat dieksekusi lagi. Jadi!timeout
bagian ini pada dasarnya mengatakan 'maaf bub, ini sudah dieksekusi dalam jendela yang ditentukan` ... ingat fungsi setTimeout akan menghapusnya, memungkinkan panggilan berikutnya untuk dieksekusi.setTimeout
fungsi? Juga, saya telah mencoba kode ini, bagi saya, mengirimkantrue
langsung hanya mencegah fungsi dipanggil sama sekali (daripada dipanggil setelah penundaan). Apakah ini terjadi untukmu?Hal penting yang perlu diperhatikan di sini adalah
debounce
menghasilkan fungsi yang "ditutup"timeout
variabel. Thetimeout
variabel tetap dapat diakses selama setiap panggilan dari fungsi diproduksi bahkan setelahdebounce
itu sendiri telah kembali, dan dapat berubah dari panggilan yang berbeda.Gagasan umum
debounce
adalah sebagai berikut:Poin pertama adalah adil
var timeout;
, memang adilundefined
. Untungnya,clearTimeout
cukup longgar tentang inputnya: melewatkanundefined
pengenal waktu menyebabkannya tidak melakukan apa-apa, itu tidak menimbulkan kesalahan atau sesuatu.Poin kedua dilakukan oleh fungsi yang diproduksi. Pertama-tama menyimpan beberapa informasi tentang panggilan (
this
konteks danarguments
) dalam variabel sehingga nantinya dapat menggunakan ini untuk panggilan yang dibatalkan. Ini kemudian menghapus batas waktu (jika ada satu set) dan kemudian membuat yang baru untuk menggantinya menggunakansetTimeout
. Perhatikan bahwa ini menimpa nilaitimeout
dan nilai ini bertahan selama beberapa panggilan fungsi! Ini memungkinkan debounce benar-benar berfungsi: jika fungsinya disebut berkali-kali,timeout
ditimpa beberapa kali dengan timer baru. Jika ini tidak terjadi, beberapa panggilan akan menyebabkan beberapa timer dimulai yang semuanya tetap aktif - panggilan hanya akan ditunda, tetapi tidak ditolak.Poin ketiga dilakukan dalam callback timeout. Ini menghapus
timeout
variabel dan melakukan panggilan fungsi sebenarnya menggunakan informasi panggilan yang disimpan.The
immediate
bendera seharusnya mengontrol apakah fungsi harus dipanggil sebelum atau setelah timer. Jika yafalse
, fungsi asli tidak dipanggil hingga setelah penghitung waktu diaktifkan. Jika yatrue
, fungsi asli pertama kali dipanggil dan tidak akan dipanggil lagi sampai timer dihidupkan.Namun, saya percaya bahwa
if (immediate && !timeout)
cek yang salah:timeout
baru saja siap untuk timer identifier dikembalikan olehsetTimeout
begitu!timeout
selalufalse
pada saat itu dan dengan demikian fungsi tidak bisa disebut. Versi underscore.js saat ini tampaknya memiliki pemeriksaan yang sedikit berbeda, di mana ia mengevaluasiimmediate && !timeout
sebelum meneleponsetTimeout
. (Algoritma ini juga sedikit berbeda, misalnya tidak digunakanclearTimeout
.) Itu sebabnya Anda harus selalu mencoba menggunakan versi terbaru perpustakaan Anda. :-)sumber
!timeout
di akhir? Mengapa tidak selalu ada (karena diatur kesetTimeout(function() etc.)
debounce
, ya, tetapi dibagikan di antara panggilan ke fungsi yang dikembalikan (yang merupakan fungsi yang akan Anda gunakan). Misalnya, dalamg = debounce(f, 100)
, nilaitimeout
tetap dari beberapa panggilang
. The!timeout
cek di akhir adalah kesalahan saya percaya, dan tidak dalam kode underscore.js saat ini.null
. Dalam pengujian saya dengan kode di atas, pengaturan langsung ke true membuat fungsi tidak memanggil sama sekali, seperti yang Anda sebutkan. Ada solusi tanpa garis bawah?Fungsi-fungsi yang di-debug tidak dieksekusi ketika dipanggil, mereka menunggu jeda doa selama durasi yang dapat dikonfigurasi sebelum mengeksekusi; setiap doa baru me-restart timer.
Fungsi-fungsi yang diperlambat menjalankan dan kemudian menunggu durasi yang dapat dikonfigurasi sebelum memenuhi syarat untuk memecat lagi.
Debounce sangat bagus untuk acara penekanan tombol; ketika pengguna mulai mengetik dan kemudian berhenti Anda mengirim semua penekanan tombol sebagai peristiwa tunggal, sehingga mengurangi doa penanganan.
Throttle sangat bagus untuk titik akhir waktu nyata yang Anda hanya ingin memungkinkan pengguna untuk memanggil sekali per periode waktu yang ditentukan.
Lihat juga Underscore.js untuk implementasinya.
sumber
Saya menulis posting berjudul Demistifying Debounce di JavaScript di mana saya menjelaskan dengan tepat bagaimana fungsi debounce bekerja dan menyertakan demo.
Saya juga tidak sepenuhnya mengerti bagaimana fungsi debounce bekerja ketika saya pertama kali menemukannya. Meskipun ukurannya relatif kecil, mereka sebenarnya menggunakan beberapa konsep JavaScript yang cukup canggih! Memiliki pegangan yang baik pada ruang lingkup, penutupan dan
setTimeout
metode akan membantu.Dengan itu, di bawah ini adalah fungsi dasar debounce yang dijelaskan dan didemokan di posting saya yang dirujuk di atas.
Produk jadi
Penjelasan
sumber
Yang ingin Anda lakukan adalah sebagai berikut: Jika Anda mencoba memanggil fungsi secara berurutan, yang pertama harus dibatalkan dan yang baru harus menunggu batas waktu yang diberikan dan kemudian jalankan. Jadi, Anda perlu beberapa cara untuk membatalkan batas waktu dari fungsi pertama? Tapi bagaimana caranya? Anda bisa memanggil fungsi tersebut, dan meneruskan id timeout-kembali dan kemudian memberikan ID itu ke fungsi baru. Tetapi solusi di atas jauh lebih elegan.
Apa yang dilakukannya secara efektif membuat
timeout
variabel tersedia dalam lingkup fungsi yang dikembalikan. Jadi ketika acara 'resize' dipecat, ia tidak menelepondebounce()
lagi, makatimeout
isinya tidak berubah (!) Dan masih tersedia untuk "panggilan fungsi selanjutnya".Kuncinya di sini adalah pada dasarnya bahwa kita memanggil fungsi internal setiap kali kita memiliki ukuran peristiwa. Mungkin lebih jelas jika kita membayangkan semua peristiwa-ukuran dalam array:
Anda melihat
timeout
tersedia untuk iterasi berikutnya? Dan tidak ada alasan, menurut saya untuk mengubah namathis
untukcontent
danarguments
untukargs
.sumber
this
danarguments
perubahan di dalam fungsi callback setTimeout (). Anda harus menyimpan salinan di tempat lain atau info itu hilang.Ini adalah variasi yang selalu mengaktifkan fungsi yang didebok saat pertama kali dipanggil, dengan variabel yang lebih deskriptif bernama:
sumber
Metode Debounce sederhana dalam javascript
Runtime Example JSFiddle: https://jsfiddle.net/arbaazshaikh919/d7543wqe/10/
sumber
Fungsi debounce sederhana: -
HTML: -
Javascript: -
sumber