Gesaan dan konteks
Kotak carian meminta cadangan setiap kali inputnya berubah. Pengguna menaip hello dengan pantas, jadi pelayar menghantar permintaan untuk h, he, hel, hell, dan hello, tetapi rangkaian tidak menjamin bahawa respons tiba dalam susunan tersebut. Permintaan lama mungkin selesai paling akhir dan menggantikan hasil hello dengan hell; pengguna juga mungkin mengosongkan input, menukar rangkaian, atau meninggalkan halaman.
Reka bentuk kitaran hayat permintaan, peraturan komit hasil, strategi pembatalan, dasar cache dan kesegaran, keadaan pemuatan dan ralat, maklum balas kebolehcapaian, serta pelan pengesahan. Terangkan pertanyaan mana yang diwakili oleh hasil yang kelihatan dan bukannya hanya mengatakan "tambah debounce."
Ini sesuai untuk temuduga frontend kanan, React, dan infrastruktur UI. Dokumentasi rasmi React menggunakan penaipan pantas untuk menerangkan keadaan perlumbaan (race condition) pengambilan data dan mengesyorkan agar mengabaikan respons lapuk semasa pembersihan Effect. MDN mendokumenkan bahawa AbortController.abort() boleh menamatkan fetch, penggunaan response-body, atau strim. Panduan stale-while-revalidate daripada web.dev menambah pertukaran kompromi cache dalam menyajikan nilai lama yang boleh diterima semasa menyegarkannya. Sumber-sumber ini menyokong keterwakilan teknikal topik ini, tetapi tidak menetapkan soalan syarikat yang tetap atau kekerapan temuduga. Kategorinya ialah frontend kerana kemahiran terasnya ialah keadaan tak segerak (asynchronous state) sebelah pelayar, ketekalan paparan (render consistency), dan maklum balas interaksi.
Perkara yang dinilai oleh penemuduga
Pertama, bolehkah calon membezakan permintaan yang selesai daripada permintaan yang masih layak untuk dikomit? Promise yang selesai dahulu tidak bermakna ia mewakili pertanyaan semasa. Setiap permintaan memerlukan identiti yang stabil, dan identiti atau kunci pertanyaan tersebut mesti masih sepadan pada masa komit.
Kedua, adakah mereka memahami bahawa pembatalan adalah pengurusan sumber? AbortController boleh mengurangkan kerja yang sia-sia, tetapi pembatalan mungkin berlaku selepas pelayan memproses permintaan tersebut. Abort bukanlah rollback perniagaan dan tidak boleh menggantikan perlindungan hasil lapuk.
Ketiga, bolehkah mereka memodelkan mesin keadaan (state machine) yang lengkap: input kosong, pemuatan pertama, penyegaran dengan hasil sedia ada, kejayaan, hasil kosong, ralat yang boleh dicuba semula, cache lapuk, dan unmount semuanya memerlukan peraturan yang jelas. Mengekalkan hasil lama semasa memuatkan pertanyaan baharu atau menunjukkan skeleton bergantung pada semantik pertanyaan dan risiko mengelirukan pengguna.
Akhir sekali, bolehkah mereka mengesahkan tingkah laku dengan mengawal susunan respons dan merangkumi penaipan pantas, pengosongan input, percubaan semula, cache hit, unmount, dan pengumuman kebolehcapaian daripada hanya menguji respons kejayaan yang tiba mengikut susunan?
Soalan penjelasan untuk ditanya terlebih dahulu
- Adakah setiap ketukan kekunci mesti mencetuskan permintaan? Jika produk menunggu jeda seketika, debounce adalah berguna, tetapi ia hanya mengurangkan permintaan dan tidak menyelesaikan perlumbaan antara permintaan yang telah dihantar.
- Bolehkah hasil lama kekal kelihatan? Cadangan selalunya boleh kekal semasa penyegaran jika ia dilabelkan sebagai milik pertanyaan sebelumnya; sebut harga kewangan atau hasil kebenaran mungkin perlu dikosongkan untuk mengelakkan pemilihan yang salah.
- Apakah yang membatalkan kunci cache? Rentetan pertanyaan, penapis, bahasa, skop akaun, dan versi data semuanya mungkin penting. Melakukan caching berdasarkan URL halaman sahaja boleh mencampuradukkan kebenaran atau penapis yang berbeza.
- Adakah pelayan menyokong pembatalan atau penyahduplikasian? Klien masih memerlukan kawalan ketepatan; pembatalan pelayan menambah baik penggunaan sumber tetapi tidak dapat membuktikan bahawa permintaan lama tidak mempunyai kesan.
- Adakah input memerlukan maklum balas pembaca skrin secara langsung? Bilangan hasil atau keadaan pemuatan boleh menggunakan kawasan
statussedia ada secara sopan (polite), tetapi setiap aksara tidak sepatutnya mengganggu pengguna.
Rangka jawapan 30 saat
"Saya mewakili setiap pertanyaan dengan kunci permintaan dan hanya membenarkan respons mengemas kini hasil jika kunci tersebut masih sama dengan pertanyaan semasa. Semasa pembersihan, saya memanggil AbortController.abort() untuk melepaskan kerja rangkaian dan pembacaan body, tetapi saya tidak menganggap pembatalan sebagai rollback; walaupun abort gagal, semakan identiti akan menggugurkan respons lapuk. Menetapkan debounce selepas pengguna berhenti seketika mengurangkan hingar tetapi tidak menggantikan perlindungan perlumbaan. Keadaan membezakan kosong, memuatkan, menyegarkan hasil lama, kejayaan, hasil kosong, dan ralat yang boleh dicuba semula. Cache menggunakan kunci pertanyaan lengkap dan tetingkap kesegaran yang jelas. Ujian memaksa permintaan lama kembali selepas permintaan baharu dan merangkumi pengosongan, unmount, percubaan semula, caching, serta maklum balas pembaca skrin."
Jawapan mendalam
1. Tentukan invarian komit hasil
Kekalkan currentKey, status, visibleData, dan cache pilihan. currentKey merangkumi pertanyaan yang dinormalkan dan setiap penapis, bahasa, serta skop akaun yang mengubah hasil. Setiap permintaan rangkaian mendapat requestId yang unik; penutupannya (closure) mengekalkan kunci dan pengawalnya.
Sebelum mengkomit hasil, pastikan permintaan belum dibatalkan dan kuncinya masih sama dengan kunci semasa. Hanya selepas itu ia boleh menulis data yang kelihatan, ralat, atau keadaan kejayaan. Invarian ini lebih selamat daripada menganggap "permintaan terakhir biasanya selesai paling akhir," kerana rangkaian tidak memberikan jaminan susunan sedemikian.
Anggap UI sebagai unjuran tulen daripada kunci pertanyaan semasa, entri cache terbaharu yang boleh digunakan, permintaan aktif, dan ralat. Elakkan beberapa Effect menyegerakkan nilai loading, data, dan error yang bebas; mengosongkan atau menggantikan pertanyaan dengan pantas sebaliknya boleh menulis ralat lama ke dalam keadaan baharu.
2. Asingkan debounce, throttle, dan perlindungan perlumbaan
Debounce menggabungkan input pantas menjadi satu permintaan dan berguna untuk cadangan. Throttle mengehadkan permintaan dalam tetingkap masa dan berguna untuk menatal atau memantau. Kedua-duanya mengawal bila permintaan bermula; tiada satu pun menghalang permintaan yang telah dihantar daripada tiba lewat.
Walaupun dengan debounce 250 milisaat, pengguna boleh menaip semula semasa permintaan sedang dalam perjalanan. Kekalkan semakan identiti. Contoh rasmi React menetapkan bendera ignore dalam pembersihan Effect supaya respons lama tidak lagi memanggil setResults; jujukan yang meningkat (incrementing sequence), perbandingan kunci pertanyaan, atau mesin keadaan eksplisit melaksanakan peraturan yang sama.
3. Anggap pembatalan sebagai pengoptimuman, bukan bukti ketepatan
Berikan setiap permintaan aktif AbortController tersendiri. Apabila pertanyaan berubah, input dikosongkan, komponen dinyahlekap (unmount), atau permintaan gantian bermula, panggil abort(). Kendalikan AbortError sebagai pembatalan yang dijangka: jangan paparkannya sebagai kegagalan rangkaian dan jangan biarkan ia menimpa keadaan pertanyaan baharu.
Isyarat pembatalan mungkin tiba terlalu lewat untuk menghentikan pemprosesan pelayan atau mungkin hanya menghentikan pembacaan di sebelah pelayar. "Batalkan permintaan lama" dan "permintaan lama tidak menghasilkan kesan sebelah pelayan" adalah dua dakwaan yang berbeza. GET carian biasanya tidak mempunyai kesan sampingan penulisan, tetapi masih memerlukan kawalan requestId; operasi yang tidak boleh diterbalikkan memerlukan kontrak ketakberubahan (idempotency) yang jelas.
4. Pilih antara hasil lama, skeleton, dan cache
Tanpa data pada pertanyaan pertama, tunjukkan pemegang tempat pemuatan dan teks status kebolehcapaian. Semasa penyegaran, kekalkan hasil lama jika ia kekal selamat, labelkan pertanyaan miliknya, dan tunjukkan penunjuk penyegaran yang ringan. Jika data lama boleh menyebabkan pemilihan yang memudaratkan, kosongkannya atau jadikannya tidak boleh diambil tindakan.
Kunci cache mesti mengandungi input pertanyaan yang lengkap. Padanan cache (hit) boleh dipaparkan serta-merta dan kemudian disahkan semula di latar belakang, tetapi rekodkan masa, sumber, dan ralatnya supaya data lapuk atau data dengan perubahan kebenaran tidak dibentangkan sebagai fakta semasa. Stale-while-revalidate menyajikan nilai lama yang boleh diterima dahulu dan mengambil nilai baharu secara tak segerak; produk mesti menentukan tetingkap kesegaran yang boleh diterima.
5. Kendalikan ralat, hasil kosong, dan percubaan semula
Hasil kosong ialah keadaan yang berjaya, bukan ralat rangkaian. Ikatkan ralat pada kunci semasanya; ralat daripada pertanyaan lama akan dibuang. Ralat yang boleh dicuba semula mengekalkan maklumat pertanyaan dan backoff. Percubaan semula mencipta requestId baharu dan bukannya menggunakan semula Promise yang telah ditandakan lapuk.
Jika pelayan mengembalikan 401, skop kebenaran yang berubah, atau syarat pertanyaan tidak sah, kosongkan atau sahkan semula cache dan bukannya mencuba semula selama-lamanya. Semasa pemulihan rangkaian, minta hanya kunci semasa supaya peristiwa pemulihan tidak mengisi semula pertanyaan yang telah dikosongkan oleh pengguna.
6. Kekalkan maklum balas papan kekunci dan teknologi bantuan
Jangan alihkan fokus input apabila hasil disegarkan. Gunakan identiti senarai yang stabil supaya penyahlekapan hasil lama tidak menyebabkan pembaca skrin membaca semula keseluruhan senarai. Letakkan pemuatan, bilangan hasil, dan ralat di kawasan status yang sopan (polite) yang sedia ada, dan kemas kini hanya untuk perubahan keadaan yang bermakna.
Pengguna papan kekunci harus boleh terus menaip, membatalkan, atau memilih hasil semasa memuatkan. Jika sesuatu hasil lapuk, sahkan bahawa kunci pertanyaannya masih sepadan sebelum menggunakan pemilihan tersebut. Warna tidak boleh menjadi satu-satunya isyarat pemuatan atau ralat; kaitkan teks ralat dengan input atau senarai.
7. Uji mesin keadaan dengan susunan terkawal
Gantian ujian pengangkutan (transport test double) harus menjeda setiap permintaan dan melepaskan respons secara manual. Rangkumi permintaan lama yang berjaya selepas permintaan baharu, kegagalan lama yang tiba selepas kejayaan baharu, respons lapuk selepas pengosongan, kegagalan penyegaran latar belakang selepas cache hit, respons selepas unmount, AbortError, dan menaip semula semasa percubaan semula.
Selepas setiap peristiwa, pastikan (assert) kunci semasa, hasil yang kelihatan, status, cap masa cache, dan pengumuman pembaca skrin. Sahkan bahawa muatan yang sama yang tiba dalam susunan berbeza tidak menyebabkan pemaparan pendua atau kehilangan fokus. Jejaki kiraan permintaan, kadar pembatalan, respons lapuk yang digugurkan, kependaman hasil yang kelihatan, dan kadar percubaan semula, tetapi jangan gunakan permintaan yang lebih sedikit untuk menyembunyikan hasil yang salah.
Contoh jawapan berkualiti tinggi
"Saya mula-mula menormalkan pertanyaan lengkap menjadi kunci yang mengandungi teks, penapis, bahasa, dan skop kebenaran. Setiap permintaan sebenar mendapat requestId dan AbortController, serta merekodkan kunci semasa. Respons mesti melepasi kedua-dua semakan—requestId-nya masih aktif dan kuncinya masih sepadan—sebelum ia boleh mengkomit kejayaan, hasil kosong, atau ralat. Apabila input berubah, saya membatalkan pengawal lama dan mengendalikan AbortError secara senyap, tetapi saya tidak mendakwa bahawa pembatalan tersebut telah membalikkan pemprosesan pelayan.
Saya menghantar permintaan selepas jeda 250 milisaat untuk mengurangkan hingar. Pemuatan pertama menunjukkan pemegang tempat. Semasa penyegaran, saya mengekalkan hasil lama hanya apabila ia selamat, melabelkannya sebagai milik pertanyaan sebelumnya, dan sebaliknya mengosongkannya. Entri cache menggunakan kunci penuh dan boleh dipaparkan seketika sebelum pengesahan latar belakang; entri yang melebihi tetingkap kesegaran hanya menunjukkan status memuatkan.
Mesin keadaan membezakan input kosong, memuatkan, menyegarkan data lama, kejayaan, hasil kosong, dan ralat yang boleh dicuba semula. Ralat terikat pada kunci, jadi ralat lama yang lewat akan dibuang. Fokus kekal pada input, identiti hasil kekal stabil, dan kawasan polite yang sedia ada mengumumkan perubahan keadaan yang bermakna dan bukannya setiap aksara.
Saya kemudian memaksa hell kembali selepas hello, menghantar respons lapuk selepas pengosongan, menjadikan pembatalan gagal, menggagalkan penyegaran cache, menghantar respons selepas unmount, dan menaip semula semasa percubaan semula. UI akhir mesti boleh dijelaskan hanya oleh kunci semasa."
Kesilapan lazim
- Hanya menggunakan debounce → permintaan yang telah dihantar masih boleh berlumba → kekalkan requestId atau kawalan kunci.
- Menunjukkan respons terakhir yang selesai → susunan penyiapan rangkaian bukan susunan pertanyaan → hanya kunci semasa boleh dikomit.
- Menganggap abort sebagai rollback → pelayan mungkin telah memprosesnya → gunakan pembatalan untuk pembersihan dan peraturan identiti/versi untuk ketepatan.
- Satu entri cache untuk setiap pertanyaan → penapis, bahasa, atau skop boleh bocor merentas hasil → sertakan setiap input hasil dalam kunci.
- Membiarkan ralat lama menimpa pertanyaan baharu → pengguna melihat kegagalan lapuk → ikat ralat pada requestId dan kunci.
- Mengosongkan UI untuk setiap pemuatan → pengguna kehilangan konteks yang berguna → pilih hasil lama atau skeleton berdasarkan risiko data yang mengelirukan.
- Mengumumkan setiap ketukan kekunci → pembaca skrin kerap terganggu → umumkan perubahan pemuatan, hasil, dan ralat yang bermakna.
- Hanya menguji kejayaan yang tersusun → keadaan perlumbaan sebenar tidak wujud → kawal susunan respons, pembatalan, pengosongan, unmount, dan percubaan semula.
Soalan susulan dan jawapan
Adakah kunci mencukupi untuk penomboran halaman (pagination) atau tatalan tak terhingga (infinite scrolling)?
Sertakan penapis, susunan, kursor, atau halaman dalam kunci permintaan dan ikat setiap halaman pada versi pertanyaan. Pertanyaan baharu membuang halaman lama. Memuatkan halaman lain untuk pertanyaan yang sama boleh mengekalkan halaman sebelumnya kelihatan, tetapi kursor pendua dan halaman lapuk tidak boleh menimpa senarai yang disahkan. Gunakan kursor seterusnya yang disediakan oleh pelayan dan bukannya menyimpulkan susunan daripada nombor halaman klien.
Apakah yang berubah apabila pengguna menaip di luar talian dan menyambung semula?
Carian biasanya tidak perlu mengekalkan setiap permintaan lama; kekalkan input semasa dan cache terakhir yang boleh diterima. Apabila menyambung semula, minta hanya kunci semasa dan abaikan kerja luar talian yang lapuk. Jika cadangan luar talian ialah keperluan produk, umur cache, skop data, dan kesegaran mesti kelihatan supaya hasil luar talian tidak dibentangkan sebagai masa nyata.
Bolehkah React Query atau SWR menyelesaikan perkara ini sahaja?
Pustaka cache boleh menyediakan penyahduplikasian, caching, pembatalan, dan pengurusan kitaran hayat, tetapi produk tetap mentakrifkan kunci pertanyaan, kelapukan yang boleh diterima, percubaan semula, dan keadaan interaksi. Pembatalan pustaka atau masa lapuk lalai tidak boleh menentukan skop kebenaran, risiko data yang mengelirukan, atau maklum balas kebolehcapaian. Sahkan semantik perlumbaan pustaka dan kodkan peraturan tersebut dalam kunci pertanyaan dan keadaan UI.
Adakah pembatalan selamat jika carian bertukar menjadi POST dengan pengelogan audit?
Jangan anggap ia selamat. POST mungkin mempunyai kesan sampingan sebelah pelayan, dan pembatalan klien tidak membatalkan transaksi. Gunakan kunci ketakberubahan (idempotency key), status penyerahan yang jelas, dan titik akhir status pertanyaan; tunjukkan kejayaan hanya selepas pengesahan berwibawa. POST masih munasabah untuk pertanyaan kompleks yang bebas daripada kesan sampingan, tetapi kontrak percubaan semula dan pembatalannya mestilah jelas.