Melantun dan Mendikit

王林
Lepaskan: 2024-08-09 20:32:30
asal
477 orang telah melayarinya

Debouncing and Throttling

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.

Debouncing

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} />
Salin selepas log masuk

Pendekatan ini kelihatan baik tetapi ia mempunyai beberapa isu:

  1. Anda sedang membuat panggilan API pada setiap acara akhbar kekunci. Jika pengguna menaip 15 aksara, itu adalah 15 panggilan API untuk seorang pengguna. Ini tidak akan berskala.
  2. Apabila hasil daripada 15 panggilan API ini tiba, anda hanya memerlukan yang terakhir. Keputusan daripada 14 panggilan sebelumnya akan dibuang. Ia memakan banyak lebar jalur pengguna dan pengguna pada rangkaian perlahan akan mengalami kelewatan yang ketara.
  3. Pada UI, 15 panggilan API ini akan mencetuskan pemaparan semula. Ia akan menjadikan komponen itu lagging.

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)} />
Salin selepas log masuk

Kami telah melanjutkan kod sedia ada kami untuk menggunakan nyahlantun.

Fungsi nyahlantun ialah fungsi utiliti generik yang mengambil dua hujah:

  1. fn: Panggilan fungsi yang sepatutnya ditangguhkan.
  2. kelewatan: Kelewatan dalam milisaat.

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.

Pendikit

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:

  1. Pendekatan Noob: Bila-bila masa pengguna menggerakkan penuding tetikus mereka atau menaip sesuatu, buat panggilan API. Anda sudah tahu betapa teruknya ia boleh menjadi.
  2. Pendekatan Debouncing: Ia menyelesaikan bahagian prestasi sesuatu tetapi dari perspektif UX ia adalah mengerikan. Rakan sekerja anda mungkin menulis perenggan 300 patah perkataan dan anda hanya dimaklumkan sekali pada akhirnya. Adakah ia masih dianggap masa nyata?

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)} />
Salin selepas log masuk

Kami telah mengubah suai kod sedia ada kami untuk menggunakan fungsi pendikit. Ia memerlukan dua hujah:

  1. fn: Fungsi sebenar untuk pendikit.
  2. masa: Selang selepas fungsi itu dibenarkan untuk dilaksanakan.

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);
    }
  }
 }
}
Salin selepas log masuk

Pelaksanaan yang dikemas kini ini memastikan kami tidak terlepas sebarang data.

Lodash juga menyediakan fungsi utiliti pendikit.


Ringkasan

  1. Menyahlantun dan Mendikit ialah teknik pengoptimuman prestasi.
  2. Kedua-dua ini berfungsi pada prinsip yang sama - tangguhkan perkara.
  3. Debounce menunggu t selepas acara terakhir diterima manakala Throttling melaksanakan fn secara berkala dalam masa t.
  4. Menyahlantun digunakan dalam ciri carian dan Pendikit digunakan dalam apl Masa Nyata (tidak terhad kepada ini).

Sumber

FrontendCamp
lodash

Atas ialah kandungan terperinci Melantun dan Mendikit. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan