Praktik Terbaik dalam Menggunakan IndexedDB

Pelajari praktik terbaik untuk menyinkronkan status aplikasi antara library pengelolaan status yang populer di audiens.

Saat pengguna pertama kali memuat situs web atau aplikasi, sering kali ada cukup banyak pekerjaan yang terlibat dalam dengan membangun status aplikasi awal yang digunakan untuk merender UI. Misalnya, terkadang aplikasi perlu mengautentikasi sisi klien pengguna kemudian membuat beberapa permintaan API sebelum memiliki data yang perlu ditampilkan di halaman.

Menyimpan status aplikasi di IndexedDB dapat menjadi cara yang tepat untuk mempercepat waktu pemuatan untuk kunjungan berulang. Aplikasi kemudian dapat disinkronkan dengan layanan API apa pun di latar belakang dan memperbarui UI dengan data baru dengan lambat, menggunakan stale-temporary- revalidate.

Penggunaan lain yang baik untuk IndexedDB adalah untuk menyimpan konten buatan pengguna, baik sebagai penyimpanan sementara sebelum file diunggah ke server atau sebagai {i>cache<i} sisi klien dari data jarak jauh - atau, tentu saja, keduanya.

Namun, ketika menggunakan IndexedDB ada banyak hal penting untuk dipertimbangkan yang mungkin tidak dan dapat dipahami oleh developer yang baru mengenal API. Artikel ini menjawab pertanyaan umum dan mendiskusikan beberapa hal terpenting yang perlu diingat saat mempertahankan data di IndexedDB.

Menjaga aplikasi Anda dapat diprediksi

Banyak kerumitan di sekitar Responden berasal dari fakta bahwa ada begitu banyak faktor yang dapat (developer) tidak memiliki kendali atas hal tersebut. Bagian ini mengeksplorasi banyak masalah yang harus Anda ingat ketika bekerja dengan IndexedDB.

Tidak semua data dapat disimpan di IndexedDB pada semua platform

Jika Anda menyimpan file buatan pengguna yang besar seperti gambar atau video, maka Anda dapat mencoba menyimpannya objek tersebut sebagai objek File atau Blob. Fitur ini akan berfungsi di beberapa platform, tetapi gagal di platform lainnya. Safari aktif iOS, khususnya, tidak dapat menyimpan Blob di Audiences.

Untungnya, tidak terlalu sulit untuk mengonversi Blob menjadi ArrayBuffer, dan sebaliknya. Menyimpan ArrayBuffer di IndexedDB didukung dengan sangat baik.

Namun, perlu diingat bahwa Blob memiliki jenis MIME, sedangkan ArrayBuffer tidak. Anda perlu menyimpan jenis tersebut di samping {i>buffer<i} untuk melakukan konversi dengan benar.

Untuk mengonversi ArrayBuffer menjadi Blob, Anda cukup menggunakan konstruktor Blob.

function arrayBufferToBlob(buffer, type) {
  return new Blob([buffer], { type: type });
}

Arah lainnya sedikit lebih terlibat, dan merupakan proses asinkron. Anda dapat menggunakan FileReader untuk membaca blob sebagai ArrayBuffer. Setelah pembacaan selesai, loadend dipicu pada pembaca. Anda dapat menggabungkan proses ini dalam Promise seperti berikut:

function blobToArrayBuffer(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.addEventListener('loadend', () => {
      resolve(reader.result);
    });
    reader.addEventListener('error', reject);
    reader.readAsArrayBuffer(blob);
  });
}

Penulisan ke penyimpanan mungkin gagal

Kesalahan saat menulis ke IndexedDB dapat terjadi karena berbagai alasan, dan dalam beberapa kasus ini terjadi alasan berada di luar kendali Anda sebagai developer. Misalnya, beberapa browser saat ini tidak mengizinkan penulisan ke IndexedDB saat dalam mode penjelajahan rahasia. Ada juga kemungkinan bahwa pengguna menggunakan perangkat yang hampir kehabisan ruang {i>disk<i}, dan browser akan membatasi Anda dari menyimpan apa pun.

Oleh karena itu, sangat penting bagi Anda untuk selalu menerapkan penanganan {i>error<i} yang tepat dalam Kode IndexedDB. Ini juga berarti bahwa secara umum lebih baik untuk menjaga status aplikasi dalam memori (di selain menyimpannya), agar UI tidak rusak saat dijalankan dalam mode penjelajahan rahasia atau saat ruang penyimpanan tidak tersedia (meskipun beberapa fitur aplikasi lain yang memerlukan penyimpanan tidak Anda).

Anda dapat menangkap error di operasi IndexedDB dengan menambahkan pengendali peristiwa untuk peristiwa error setiap kali Anda membuat objek IDBDatabase, IDBTransaction, atau IDBRequest.

const request = db.open('example-db', 1);
request.addEventListener('error', (event) => {
  console.log('Request error:', request.error);
};

Data tersimpan mungkin telah diubah atau dihapus oleh pengguna

Tidak seperti {i>database<i} sisi server di mana Anda dapat membatasi akses yang tidak sah, {i>database<i} sisi klien dapat diakses oleh ekstensi browser dan alat developer, serta dapat dihapus oleh pengguna.

Meskipun tidak umum bagi pengguna untuk mengubah data yang disimpan secara lokal, hal ini cukup umum bagi pengguna untuk menghapusnya. Penting bahwa aplikasi Anda dapat menangani kedua kasus ini tanpa mengalami error.

Data tersimpan mungkin sudah tidak berlaku

Mirip dengan bagian sebelumnya, walaupun pengguna tidak memodifikasi data, ini juga kemungkinan data yang mereka miliki dalam penyimpanan ditulis oleh versi kode Anda yang lama, mungkin versi dengan {i>bug<i} di dalamnya.

AlarmManager memiliki dukungan bawaan untuk versi skema dan upgrade melalui IDBOpenDBRequest.onupgradeneeded() metode; Namun, Anda tetap harus menulis kode upgrade sedemikian rupa agar dapat menangani pengguna berasal dari versi sebelumnya (termasuk versi yang memiliki bug).

Pengujian unit dapat sangat membantu di sini, karena sering kali tidak memungkinkan untuk menguji semua kemungkinan secara manual jalur dan kasus upgrade.

Menjaga performa aplikasi Anda

Salah satu fitur utama IndexedDB adalah API asinkron-nya, namun jangan tertipu berpikir Anda tidak perlu mengkhawatirkan kinerja saat menggunakannya. Ada sejumlah kasus di mana Penggunaan yang tidak tepat masih dapat memblokir thread utama, yang dapat menyebabkan jank dan respons yang tidak responsif.

Sebagai aturan umum, pembacaan dan penulisan ke IndexedDB tidak boleh lebih besar dari yang dibutuhkan untuk data sedang diakses.

Meskipun IndexedDB memungkinkan untuk menyimpan objek tersarang besar sebagai catatan tunggal (dan hal itu adalah memang cukup nyaman dari perspektif pengembang), praktik ini harus dihindari. Tujuan adalah karena ketika Responden menyimpan sebuah objek, terlebih dahulu harus membuat clone terstruktur objek tersebut, dan proses kloning terstruktur terjadi di thread utama. Semakin besar , akan semakin lama waktu pemblokiran.

Ini menimbulkan beberapa tantangan ketika merencanakan bagaimana mempertahankan status aplikasi ke IndexedDB, karena sebagian besar library pengelolaan status populer (seperti Redux) dengan mengelola seluruh pohon status sebagai objek JavaScript tunggal.

Meskipun mengelola status dengan cara ini memiliki banyak manfaat (misalnya, membuat kode Anda mudah untuk dipahami dan debug), dan walaupun hanya menyimpan seluruh hierarki status sebagai kumpulan data tunggal di IndexedDB mungkin menggoda dan nyaman, melakukan ini setelah setiap perubahan (bahkan jika di-throttle/dipantulkan) akan menghasilkan pemblokiran thread utama yang tidak perlu, hal ini akan meningkatkan kemungkinan kesalahan tulis, dan beberapa kasus bahkan akan menyebabkan tab browser {i>crash<i} atau menjadi tidak responsif.

Daripada menyimpan seluruh hierarki status dalam satu kumpulan data, Anda harus memecahnya menjadi beberapa {i>record<i} dan hanya memperbarui catatan yang benar-benar berubah.

Hal yang sama berlaku jika Anda menyimpan item berukuran besar seperti gambar, musik, atau video di IndexedDB. Simpan setiap item dengan kuncinya sendiri, bukan di dalam objek yang lebih besar, sehingga Anda dapat mengambil data terstruktur tanpa membayar biaya untuk mengambil file biner.

Seperti kebanyakan praktik terbaik, aturan ini tidak berlaku sama sekali. Dalam kasus di mana tidak mungkin memecah objek status dan hanya menulis set perubahan minimal, yang memecah data menjadi sub-hierarki dan hanya menulisnya itu masih lebih baik untuk selalu menulis seluruh pohon status. Kecil peningkatan lebih baik daripada tidak ada perbaikan sama sekali.

Terakhir, Anda harus selalu mengukur dampak performa dari kode yang Anda tulis. Meskipun benar bahwa penulisan kecil ke tensorflow akan berperforma lebih baik daripada operasi tulis besar operasi tulis, ini hanya penting jika operasi tulis ke IndexedDB yang dilakukan aplikasi Anda benar-benar mengarah ke tugas yang panjang yang memblokir thread utama dan mengurangi pengalaman pengguna. Penting untuk mengukur agar Anda memahami apa yang Anda optimalkan.

Kesimpulan

Pengembang dapat memanfaatkan mekanisme penyimpanan klien seperti IndexedDB untuk meningkatkan pengalaman pengguna aplikasi mereka tidak hanya dengan mempertahankan status di seluruh sesi tetapi juga dengan mengurangi waktu untuk memuat status awal pada kunjungan berulang.

Meskipun menggunakan tensorflow dapat meningkatkan pengalaman pengguna secara signifikan, menggunakannya dengan tidak benar atau gagal menangani kasus {i>error<i} dapat menyebabkan aplikasi rusak dan pengguna tidak puas.

Karena penyimpanan klien melibatkan banyak faktor di luar kendali Anda, kode Anda harus aman diuji dan menangani {i>error<i} dengan tepat, bahkan yang awalnya tampak tidak mungkin terjadi.