Topik wawancara representatif

Wawancara Frontend: Bagaimana cara Anda melindungi data formulir yang belum disimpan saat terjadi perubahan siklus hidup halaman?

FrontendSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Sebuah formulir panjang kehilangan hasil edit ketika peramban seluler membekukan atau membuang tabnya. Bagaimana Anda menggabungkan event siklus hidup halaman, draf lokal, penyimpanan server, dan pemulihan bfcache?

Petunjuk dan konteks

Anda bertanggung jawab atas formulir pendaftaran multi-langkah. Pengguna berpindah tab, mengunci ponsel, bernavigasi kembali, atau meninggalkan halaman selama berjam-jam. Peramban dapat membekukan halaman, memulihkannya dari bfcache, atau membuangnya karena tekanan memori. Formulir harus memulihkan draf tanpa menimpa data server yang lebih baru.

Asumsikan formulir berisi data sensitif tetapi tidak teregulasi, pengguna dapat masuk di beberapa perangkat, dan akses jaringan bersifat terputus-putus. Jawaban harus menyatakan apa yang bersifat upaya terbaik (best effort) dan apa yang bersifat otoritatif.

Apa yang diuji oleh pewawancara

  • Apakah Anda membedakan antara visibilitas, pembekuan, pembuangan halaman, dan pemulihan bfcache.
  • Apakah Anda menghindari memperlakukan unload atau beforeunload sebagai hook persistensi yang andal.
  • Apakah draf lokal memiliki aturan kepemilikan, versi, kedaluwarsa, dan konflik.
  • Apakah pemulihan menjaga maksud pengguna tanpa mengganti data server yang lebih baru secara diam-diam.

Pertanyaan klarifikasi sebelum menjawab

  1. Apakah kehilangan draf lokal dapat diterima, atau haruskah produk memberikan jaminan pemulihan yang tahan lama (durable)? Ini menentukan apakah penyimpanan lokal adalah sebuah kemudahan atau hanya sekadar cache.
  2. Bisakah draf yang sama diedit di beberapa perangkat? Jika ya, server memerlukan kebijakan versi atau konflik.
  3. Apakah data tersebut aman untuk disimpan secara lokal? Bidang sensitif mungkin memerlukan enkripsi, penghilangan selektif, atau tidak ada persistensi lokal sama sekali.
  4. Apa kontrak pengiriman (submit)? Penyimpanan draf dan pengiriman akhir memerlukan aturan idempoten dan validasi yang berbeda.

Kerangka jawaban 30 detik

“Saya memperlakukan server sebagai sumber otoritatif dan draf lokal sebagai cache pemulihan yang terbatas. Saya mempertahankan draf berversi pada perubahan input dengan debounce, dan melakukan flush pembaruan terbaik (best-effort) saat dokumen menjadi tersembunyi. Saya menggunakan pageshow untuk memvalidasi ulang setelah pemulihan bfcache dan resume untuk menyegarkan status basi setelah pembekuan. Saya tidak pernah bergantung pada unload. Setiap draf mencatat waktu kedaluwarsa, versi skema, versi server dasar, dan bidang yang kotor (dirty fields); konflik ditampilkan atau digabungkan secara eksplisit alih-alih ditimpa secara diam-diam.”

Pembahasan mendalam langkah demi langkah

1. Memodelkan status siklus hidup

visibilitychange memberi tahu halaman bahwa halaman tersebut menjadi tersembunyi atau terlihat; ini tidak menjamin bahwa JavaScript akan terus berjalan. Peramban dapat membekukan halaman yang tersembunyi, dan halaman yang dibuang mungkin tidak akan pernah menjalankan kode pembersihan. pagehide dan pageshow menjelaskan navigasi dan pemulihan bfcache, sedangkan freeze dan resume mengekspos transisi siklus hidup Chromium.

Oleh karena itu, desain menyimpan data sebelum risiko terjadi, bukan saat unload di detik-detik terakhir. Pada visibilitychange ke hidden, jadwalkan penulisan lokal kecil dan flush jaringan best-effort. Pada pagehide, hentikan pekerjaan non-esensial dan rekam checkpoint lokal. Pada pageshow, periksa event.persisted dan validasi ulang versi server sebelum menampilkan formulir yang dipulihkan.

2. Buat draf lokal berbatas dan memiliki versi

Simpan hanya bidang yang aman untuk dipulihkan. Catatan draf dapat berisi:

text
draft_id, user_id, form_schema, base_server_version,
changed_at, expires_at, dirty_fields, values

Gunakan IndexedDB untuk data terstruktur dan indeks lokal kecil untuk pencarian. Terapkan debounce pada penulisan agar pengetikan tidak menghasilkan penulisan per ketukan tombol, batasi ukuran payload, dan hapus draf yang kedaluwarsa. Versi skema memungkinkan aplikasi memigrasikan atau membuang catatan yang tidak kompatibel alih-alih menguraikannya sebagai data saat ini.

Catatan lokal bukan pemegang otoritas. Ini adalah cache perangkat pengguna yang mungkin hilang, basi, duplikat, atau dihapus oleh peramban.

3. Flush dengan aman saat halaman menjadi tersembunyi

Saat dokumen menjadi tersembunyi, pertama-tama lakukan commit pada checkpoint lokal, lalu coba permintaan terautentikasi berukuran kecil jika produk mendukung penyimpanan latar belakang. Permintaan tersebut membawa ID draf dan versi server yang menjadi dasarnya. Server hanya menerimanya jika versinya cocok, lalu mengembalikan versi baru.

Jangan memblokir navigasi untuk permintaan yang lama. Jika permintaan tidak dapat selesai, checkpoint lokal masih melindungi perangkat ini. Hindari permintaan unload yang sinkron: ini merusak navigasi dan tidak dijamin pada jalur siklus hidup seluler.

4. Pemulihan setelah bfcache dan pembekuan (freeze)

Saat pageshow terpicu dengan persisted, halaman mungkin berisi snapshot yang secara visual lengkap tetapi secara logis sudah usang. Ambil versi server saat ini, bandingkan dengan versi dasar formulir, dan tampilkan pilihan konflik jika perangkat lain mengubah draf tersebut. Saat resume terpicu, segarkan sesi dan data yang mungkin telah kedaluwarsa saat halaman dibekukan.

Jika halaman dibuang, tidak ada status dalam memori yang dapat dilanjutkan. Pada pemuatan berikutnya, cari draf lokal yang belum kedaluwarsa, bandingkan versi dasarnya dengan server, dan tawarkan untuk memulihkan, membuang, atau menggabungkan. Pengguna harus melihat nilai mana yang lebih baru sebelum menerima penggabungan.

5. Menguji jalur kegagalan dan privasi

Uji peralihan tab, peralihan aplikasi seluler, navigasi maju/mundur, pemulihan bfcache, pembuangan oleh peramban, pengeditan offline, kehabisan kuota, migrasi skema, draf kedaluwarsa, dan konflik dua perangkat. Pastikan bahwa versi server yang lebih baru tidak pernah ditimpa secara diam-diam.

Sensor (redact) bidang sensitif dari log. Hapus draf saat penghapusan akun, patuhi periode retensi yang singkat, dan jelaskan pemulihan lokal dalam pemberitahuan privasi. Ukur keberhasilan pemulihan, tingkat konflik, kegagalan penulisan lokal, dan latensi penyimpanan server; indikator "tersimpan" harus mewakili checkpoint yang diketahui, bukan harapan bahwa handler unload telah berjalan.

Contoh jawaban berkualitas tinggi

Saya akan menjadikan server sebagai sumber kebenaran berversi dan menyimpan draf lokal yang terbatas untuk pemulihan. Perubahan input didebounce ke dalam IndexedDB dengan versi skema, masa kedaluwarsa, kumpulan dirty field, dan versi server yang digunakan sebagai dasar. Saat visibilitychange melaporkan hidden, saya menulis checkpoint dan mencoba penyimpanan terautentikasi berukuran kecil, tetapi saya tidak memblokir navigasi atau bergantung pada unload.

Pada pageshow, terutama ketika event berasal dari bfcache, saya mengambil ulang versi server sebelum mempercayai formulir yang dipulihkan. Pada resume, saya menyegarkan data dan status sesi yang mungkin telah kedaluwarsa saat dibekukan. Halaman yang dibuang dimulai dari pemuatan baru dan menawarkan draf lokal yang belum kedaluwarsa. Jika versi berbeda, saya menampilkan UI konflik atau penggabungan tingkat bidang; saya tidak pernah menimpa salinan server yang lebih baru secara diam-diam. Pengujian mencakup pembuangan pada perangkat seluler, pengeditan offline, batas kuota, dan konflik dua perangkat.

Kesalahan umum

  • Kesalahan: Menyimpan hanya di beforeunloadMengapa gagal: peramban seluler dapat menghentikan halaman tanpa memicunya dan hal ini dapat memblokir bfcache → Solusi: buat checkpoint pada input dan transisi hidden.
  • Kesalahan: Memperlakukan halaman bfcache yang terlihat sebagai halaman baru → Mengapa gagal: snapshot dapat berisi status server yang basi → Solusi: validasi ulang pada pageshow dan bandingkan versi.
  • Kesalahan: Menjadikan penyimpanan lokal sebagai otoritas → Mengapa gagal: data dapat dihapus, basi, atau tidak tersedia → Solusi: gunakan versi server dan sajikan data lokal sebagai kandidat pemulihan.
  • Kesalahan: Mencoba ulang seluruh formulir pada versi yang lebih baru → Mengapa gagal: ini menimpa hasil edit yang tidak terkait → Solusi: kirim dirty fields dengan versi optimis dan selesaikan konflik.
  • Kesalahan: Mencatat nilai draf ke log untuk debugging → Mengapa gagal: konten sensitif bocor ke telemetri → Solusi: catat hanya ID, versi, ukuran, dan hasilnya.

Pertanyaan lanjutan dan tanggapan

Haruskah saya menggunakan localStorage atau IndexedDB?

Gunakan localStorage hanya untuk metadata sinkron yang sangat kecil. IndexedDB cocok untuk draf terstruktur, payload yang lebih besar, dan penulisan asinkron. Keduanya tidak memberikan durabilitas atau otoritas lintas perangkat; keduanya memerlukan masa kedaluwarsa, penanganan kuota, pembuatan versi skema, dan aturan privasi.

Bagaimana jika pengguna mengedit secara offline di dua perangkat?

Beri setiap penyimpanan versi server dasar dan ID perangkat atau draf. Saat konektivitas kembali, terima hanya versi yang cocok, lalu tampilkan penggabungan tingkat bidang atau biarkan pengguna memilih. Kebijakan last-write-wins hanya dapat diterima jika produk secara eksplisit menerima kehilangan data secara diam-diam dan bidang-bidangnya saling independen.

Bisakah service worker menjamin penyimpanan akhir?

Tidak. Service worker dapat meningkatkan pengiriman percobaan ulang, tetapi dapat dihentikan, kehilangan akses jaringan, atau tidak tersedia dalam alur tertentu. UI harus melaporkan checkpoint yang terkonfirmasi, dan server harus membuat percobaan ulang bersifat idempoten. Draf lokal tetap menjadi cadangan (fallback) untuk perangkat yang tidak dapat menyelesaikan permintaan.

Sumber publik

Pertanyaan terkait