Memperkirakan Ruang Penyimpanan yang Tersedia

tl;dr

Chrome 61, dengan semakin banyak browser yang akan menyusul, kini menampilkan perkiraan jumlah penyimpanan yang digunakan aplikasi web dan jumlah yang tersedia melalui:

if ('storage' in navigator && 'estimate' in navigator.storage) {
  navigator.storage.estimate().then(({usage, quota}) => {
    console.log(`Using ${usage} out of ${quota} bytes.`);
  });
}

Aplikasi web modern dan penyimpanan data

Saat Anda memikirkan kebutuhan penyimpanan aplikasi web modern, ada baiknya untuk memecah apa yang disimpan menjadi dua kategori: data inti yang diperlukan untuk memuat aplikasi web, dan data yang diperlukan untuk interaksi pengguna yang bermakna setelah aplikasi dimuat.

Jenis data pertama, yang diperlukan untuk memuat aplikasi web Anda, terdiri dari HTML, JavaScript, CSS, dan mungkin beberapa gambar. Pekerja layanan, beserta Cache Storage API, menyediakan infrastruktur yang diperlukan untuk menyimpan resource inti tersebut, lalu menggunakannya nanti untuk memuat aplikasi web Anda dengan cepat, idealnya mengabaikan jaringan sepenuhnya. (Alat yang terintegrasi dengan proses build aplikasi web, seperti library Workbox baru atau sw-precache lama, dapat sepenuhnya mengotomatiskan proses penyimpanan, pembaruan, dan penggunaan jenis data ini.)

Tapi bagaimana dengan jenis data lainnya? Ini adalah resource yang tidak diperlukan untuk memuat aplikasi web, tetapi mungkin memainkan peran penting dalam pengalaman pengguna Anda secara keseluruhan. Misalnya, jika Anda menulis aplikasi web pengeditan gambar, Anda mungkin ingin menyimpan satu atau beberapa salinan lokal sebuah gambar, sehingga pengguna dapat beralih di antara revisi dan mengurungkan pekerjaannya. Atau jika Anda mengembangkan pengalaman pemutaran media offline, menyimpan file audio atau video secara lokal akan menjadi fitur yang penting. Setiap aplikasi web yang dapat dipersonalisasi pada akhirnya perlu menyimpan beberapa semacam informasi status. Bagaimana Anda tahu berapa banyak ruang yang tersedia untuk jenis penyimpanan runtime ini, dan apa yang terjadi jika Anda kehabisan ruang?

Masa lalu: window.webkitStorageInfo dan navigator.webkitTemporaryStorage

Secara historis, browser mendukung jenis introspeksi ini melalui antarmuka berawalan, seperti window.webkitStorageInfo yang sangat lama (dan tidak digunakan lagi), dan navigator.webkitTemporaryStorage yang masih non-standar. Meskipun memberikan informasi yang berguna, antarmuka ini tidak memiliki masa depan sebagai standar web.

Di situlah Standar Penyimpanan WhatWG akan masuk ke dalam gambar.

Masa depan: navigator.storage

Sebagai bagian dari upaya berkelanjutan pada Storage Living Standard, beberapa API yang berguna telah berhasil menggunakan antarmuka StorageManager, yang ditampilkan ke browser sebagai navigator.storage. Seperti banyak API web baru lainnya, navigator.storage hanya tersedia di origin yang aman (disalurkan melalui HTTPS, atau localhost).

Tahun lalu, kami memperkenalkan metode navigator.storage.persist(), yang memungkinkan aplikasi web Anda meminta agar penyimpanannya dikecualikan dari pembersihan otomatis.

Kini jenis tersebut digabungkan dengan metode navigator.storage.estimate(), yang berfungsi sebagai pengganti modern untuk navigator.webkitTemporaryStorage.queryUsageAndQuota(). estimate() menampilkan informasi serupa, tetapi menampilkan antarmuka berbasis promise, yang sesuai dengan API asinkron modern lainnya. Promise yang ditampilkan oleh estimate() diselesaikan dengan objek yang berisi dua properti: usage, yang menunjukkan jumlah byte yang saat ini digunakan, dan quota, yang mewakili byte maksimum yang dapat disimpan oleh origin saat ini. (Seperti semua hal lain yang terkait dengan penyimpanan, kuota diterapkan di seluruh origin.)

Jika aplikasi web mencoba menyimpan—menggunakan, misalnya, IndexedDB atau Cache Storage API—data yang cukup besar untuk memindahkan origin tertentu melebihi kuota yang tersedia, permintaannya akan gagal dengan pengecualian QuotaExceededError.

Penerapan estimasi penyimpanan

Cara Anda menggunakan estimate() bergantung pada jenis data yang perlu disimpan oleh aplikasi Anda. Misalnya, Anda dapat memperbarui kontrol di antarmuka Anda agar pengguna mengetahui berapa banyak ruang yang digunakan setelah setiap operasi penyimpanan selesai. Idealnya, Anda menyediakan antarmuka yang memungkinkan pengguna membersihkan data secara manual yang tidak diperlukan lagi. Anda dapat menulis kode di sepanjang baris:

// For a primer on async/await, see
// https://developers.google.com/web/fundamentals/getting-started/primers/async-functions
async function storeDataAndUpdateUI(dataUrl) {
  // Pro-tip: The Cache Storage API is available outside of service workers!
  // See https://googlechrome.github.io/samples/service-worker/window-caches/
  const cache = await caches.open('data-cache');
  await cache.add(dataUrl);

  if ('storage' in navigator && 'estimate' in navigator.storage) {
    const {usage, quota} = await navigator.storage.estimate();
    const percentUsed = Math.round(usage / quota * 100);
    const usageInMib = Math.round(usage / (1024 * 1024));
    const quotaInMib = Math.round(quota / (1024 * 1024));

    const details = `${usageInMib} out of ${quotaInMib} MiB used (${percentUsed}%)`;

    // This assumes there's a <span id="storageEstimate"> or similar on the page.
    document.querySelector('#storageEstimate').innerText = details;
  }
}

Seberapa akurat perkiraan tersebut?

Sulit untuk melewatkan fakta bahwa data yang Anda dapatkan kembali dari fungsi hanyalah perkiraan ruang asal yang digunakan. Ini tepat di nama fungsi! Baik nilai usage maupun quota tidak dimaksudkan agar stabil, jadi sebaiknya Anda mempertimbangkan hal berikut:

  • usage mencerminkan jumlah byte yang digunakan secara efektif oleh origin tertentu untuk data origin yang sama, yang dapat terpengaruh oleh teknik kompresi internal, blok alokasi berukuran tetap yang mungkin mencakup ruang yang tidak digunakan, dan adanya data"tombstone" yang mungkin dibuat sementara setelah penghapusan. Untuk mencegah kebocoran informasi ukuran yang tepat, lintas origin, resource buram yang disimpan secara lokal dapat berkontribusi byte padding tambahan pada nilai usage keseluruhan.
  • quota mencerminkan jumlah ruang yang saat ini disediakan untuk origin. Nilainya bergantung pada beberapa faktor konstan seperti ukuran penyimpanan secara keseluruhan, dan juga sejumlah faktor yang berpotensi tidak stabil, termasuk jumlah ruang penyimpanan yang saat ini tidak digunakan. Jadi, saat aplikasi lain di perangkat menulis atau menghapus data, jumlah ruang yang bersedia dialokasikan browser untuk asal aplikasi web Anda mungkin akan berubah.

Presentasi: deteksi dan penggantian fitur

estimate() diaktifkan secara default mulai Chrome 61. Firefox bereksperimen dengan navigator.storage, tetapi mulai Agustus 2017, Firefox tidak diaktifkan secara default. Anda harus mengaktifkan preferensi dom.storageManager.enabled agar dapat mengujinya.

Saat menggunakan fungsi yang belum didukung di semua browser, deteksi fitur adalah suatu keharusan. Anda dapat menggabungkan deteksi fitur dengan wrapper berbasis promise di atas metode navigator.webkitTemporaryStorage lama untuk memberikan antarmuka yang konsisten seperti:

function storageEstimateWrapper() {
  if ('storage' in navigator && 'estimate' in navigator.storage) {
    // We've got the real thing! Return its response.
    return navigator.storage.estimate();
  }

  if ('webkitTemporaryStorage' in navigator &&
      'queryUsageAndQuota' in navigator.webkitTemporaryStorage) {
    // Return a promise-based wrapper that will follow the expected interface.
    return new Promise(function(resolve, reject) {
      navigator.webkitTemporaryStorage.queryUsageAndQuota(
        function(usage, quota) {resolve({usage: usage, quota: quota})},
        reject
      );
    });
  }

  // If we can't estimate the values, return a Promise that resolves with NaN.
  return Promise.resolve({usage: NaN, quota: NaN});
}