Satu lagi antara soalan temuduga bahagian hadapan yang popular. Ia menguji pengetahuan orang yang ditemuduga tentang JS, Prestasi dan Reka Bentuk Sistem FusionExcel.
Ini ialah soalan #2 siri Soalan Temuduga Frontend. Jika anda ingin meningkatkan tahap persediaan anda atau kekal dikemas kini secara umum, pertimbangkan untuk mendaftar di FrontendCamp.
Menyahlantun dan Mendikit berfungsi pada prinsip yang sama - melengahkan perkara - tetapi masih mempunyai pendekatan dan kes penggunaan yang sangat berbeza.
Kedua-dua konsep ini berguna untuk membangunkan aplikasi berprestasi. Hampir semua tapak web yang anda lawati setiap hari menggunakan Debouncing dan Throttling dalam beberapa cara atau yang lain.
Kes penggunaan nyahlantun yang terkenal ialah kepala taip(atau autolengkap).
Bayangkan anda sedang membina ciri carian untuk tapak web E-dagang yang mempunyai beribu-ribu produk. Apabila pengguna cuba mencari sesuatu, apl anda akan membuat panggilan API untuk mengambil semua produk yang sepadan dengan rentetan pertanyaan pengguna.
const handleKeyDown = async (e) => { const { value } = e.target; const result = await search(value); // set the result to a state and then render on UI } <Input onKeyDown={handleKeyDown} />
Pendekatan ini kelihatan baik tetapi ia mempunyai beberapa isu:
Penyelesaian kepada masalah ini ialah Debouncing.
Idea asasnya ialah menunggu sehingga pengguna berhenti menaip. Kami akan menangguhkan panggilan API.
const debounce = (fn, delay) => { let timerId; return function(...args) { const context = this; if (timerId) { clearTimeout(timerId); }; timerId = setTimeout(() => fn.call(context, ...args), delay); } } const handleKeyDown = async (e) => { const { value } = e.target; const result = await search(value); // set the result to a state and then render on UI } <Input onKeyDown={debounce(handleKeyDown, 500)} />
Kami telah melanjutkan kod sedia ada kami untuk menggunakan nyahlantun.
Fungsi nyahlantun ialah fungsi utiliti generik yang mengambil dua hujah:
Di dalam fungsi, kami menggunakan setTimeout untuk menangguhkan panggilan fungsi(fn) sebenar. Jika fn dipanggil semula sebelum pemasa kehabisan, pemasa ditetapkan semula.
Dengan pelaksanaan kami yang dikemas kini, walaupun pengguna menaip 15 aksara, kami hanya akan membuat 1 panggilan API (dengan mengandaikan setiap penekanan kekunci mengambil masa kurang daripada 500 milisaat). Ini menyelesaikan semua isu yang kami hadapi semasa kami mula membina ciri ini.
Dalam pangkalan kod pengeluaran, anda tidak perlu mengekodkan fungsi utiliti nyahlantun anda sendiri. Kemungkinan syarikat anda sudah menggunakan perpustakaan utiliti JS seperti lodash yang mempunyai kaedah ini.
Nah, Debouncing bagus untuk persembahan tetapi terdapat beberapa senario di mana kita tidak mahu menunggu selama x saat sebelum dimaklumkan tentang perubahan.
Pengimejan anda sedang membina ruang kerja kolaboratif seperti Dokumen Google atau Figma. Salah satu ciri utama ialah pengguna harus mengetahui perubahan yang dibuat oleh pengguna saya yang lain dalam masa nyata.
Setakat ini kita hanya tahu dua pendekatan:
Di sinilah Throttling masuk. Ia betul-betul di tengah-tengah dua pendekatan yang dinyatakan di atas. Idea asasnya ialah - maklumkan pada selang masa berkala - bukan pada akhirnya dan bukan pada setiap penekanan kekunci, tetapi secara berkala.
const throttle = (fn, time) => { let lastCalledAt = 0; return function(...args) { const context = this; const now = Date.now(); const remainingTime = time - (now - lastCalledAt); if (remainingTime <= 0) { fn.call(context, ...args); lastCalledAt = now; } } } const handleKeyDown = async (e) => { const { value } = e.target; // save it DB and also notify other peers await save(value); } <Editor onKeyDown={throttle(handleKeyDown, 1000)} />
Kami telah mengubah suai kod sedia ada kami untuk menggunakan fungsi pendikit. Ia memerlukan dua hujah:
Pelaksanaannya adalah lurus ke hadapan. Kami menyimpan masa apabila fungsi terakhir dipanggil dalam lastCalledAt. Lain kali, apabila panggilan fungsi dibuat, kami menyemak sama ada masa telah berlalu dan barulah kami melaksanakan fn.
Kami hampir sampai, tetapi pelaksanaan ini mempunyai pepijat. Bagaimana jika panggilan fungsi terakhir dengan beberapa data dibuat dalam selang masa dan tiada panggilan dibuat selepas itu. Dengan pelaksanaan semasa kami, kami akan kehilangan beberapa data.
Untuk membetulkannya, kami akan menyimpan argumen dalam pembolehubah lain dan memulakan tamat masa untuk dipanggil kemudian jika tiada acara diterima.
const throttle = (fn, time) => { let lastCalledAt = 0; let lastArgs = null; let timeoutId = null; return function(...args) { const context = this; const now = Date.now(); const remainingTime = time - (now - lastCalledAt); if (remainingTime <= 0) { // call immediately fn.call(context, ...args); lastCalledAt = now; if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } } else { // call later if no event is received lastArgs = args; if (!timeoutId) { timeoutId = setTimeout(() => { fn.call(context, ...lastArgs); lastCalledAt = Date.now(); lastArgs = null; timeoutId = null; }, remainingTime); } } } }
Pelaksanaan yang dikemas kini ini memastikan kami tidak terlepas sebarang data.
Lodash juga menyediakan fungsi utiliti pendikit.
FrontendCamp
lodash
Atas ialah kandungan terperinci Melantun dan Mendikit. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!