重點摘要
Chrome 61 和更多瀏覽器現在會顯示預估值,說明網頁應用程式使用的儲存空間大小,以及可用的儲存空間大小:
if ('storage' in navigator && 'estimate' in navigator.storage) {
navigator.storage.estimate().then(({usage, quota}) => {
console.log(`Using ${usage} out of ${quota} bytes.`);
});
}
現代化的網頁應用程式和資料儲存空間
在思考現代網頁應用程式的儲存需求時,建議將儲存的內容分為兩類:載入網頁應用程式所需的核心資料,以及應用程式載入後用於有意義的使用者互動所需的資料。
第一類資料是載入網頁應用程式所需的資料,包括 HTML、JavaScript、CSS 和一些圖片。服務工作者和 快取儲存空間 API 可提供必要的基礎架構,用於儲存這些核心資源,並在日後用於快速載入網路應用程式,最好是完全略過網路。(與您網頁應用程式建構程序整合的工具 (例如新的 Workbox 程式庫或較舊的 sw-precache
) 可完全自動化這類資料的儲存、更新和使用程序。)
那麼其他類型的資料呢?這些資源並非載入網頁應用程式所需,但可能在整體使用者體驗中扮演重要角色。舉例來說,如果您要編寫圖片編輯網頁應用程式,可能會想儲存一或多個圖片的本機副本,讓使用者在修訂版本之間切換,並撤銷作業。或者,如果您要開發離線媒體播放體驗,則在本機儲存音訊或視訊檔案是一項重要功能。每個可進行個人化的網頁應用程式都需要儲存某種狀態資訊。如何得知這類執行階段儲存空間的可用空間,以及空間用盡時會發生什麼事?
過去:window.webkitStorageInfo
和 navigator.webkitTemporaryStorage
瀏覽器一向透過前置字串介面支援這類自省功能,例如非常舊 (且已淘汰) 的 window.webkitStorageInfo
,以及不那麼舊但仍非標準的 navigator.webkitTemporaryStorage
。雖然這些介面提供了實用的資訊,但未來不會成為網路標準。
這時就需要使用 WHATWG Storage Standard。
未來:navigator.storage
Storage Living Standard 的持續性工作中,有幾個實用的 API 已納入 StorageManager
介面,並以 navigator.storage
的形式公開給瀏覽器。與許多其他較新的網路 API 一樣,navigator.storage
僅適用於安全 (透過 HTTPS 或 localhost 提供服務) 的來源。
我們在去年推出 navigator.storage.persist()
方法,讓您的網頁應用程式可要求將其儲存空間排除在自動清理作業之外。
這項功能現在已加入 navigator.storage.estimate()
方法,可做為 navigator.webkitTemporaryStorage.queryUsageAndQuota()
的現代替代方案。estimate()
會傳回類似的資訊,但會公開以承諾為基礎的介面,這與其他新型非同步 API 相符。estimate()
傳回的承諾會解析含有兩個屬性的物件:usage
代表目前使用的位元組數,quota
代表目前來源可儲存的位元組數上限。(如同其他儲存空間相關項目,配額會套用至整個來源)。
如果網路應用程式嘗試使用 IndexedDB 或 Cache Storage API 等方式儲存過大,導致特定來源超出可用配額的資料,要求就會失敗,並擲回 QuotaExceededError
例外狀況。
儲存空間估算值的實際運作情形
具體使用 estimate()
的方式取決於應用程式需要儲存的資料類型。舉例來說,您可以更新介面中的控制項,讓使用者知道每次儲存作業完成後,系統會使用多少空間。理想情況下,您應提供介面,讓使用者手動清理不再需要的資料。您可以編寫類似以下的程式碼:
// 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;
}
}
預估值的準確度如何?
您很難忽略從函式中傳回的資料,這只是來源使用的空間的估計值。函式名稱中就包含這個字串!usage
和 quota
值都不會維持穩定,因此建議您考量以下事項:
usage
反映特定來源為同源資料有效使用的位元組數,這可能會受到內部壓縮技術、可能包含未使用的空間的固定大小配置區塊,以及在刪除後可能暫時建立的「墓碑」記錄的影響。為避免洩漏確切大小資訊,跨來源的不透明資源如果儲存在本機,可能會為整體usage
值提供額外的填充位元組。quota
反映目前為來源預留的空間量。這個值取決於一些常數因素 (例如整體儲存空間大小),以及一些可能會變動的因素,包括目前未使用的儲存空間量。因此,當裝置上的其他應用程式寫入或刪除資料時,瀏覽器願意用於網頁應用程式來源的空間量可能會有所變動。
現況:偵測功能和備用功能
estimate()
預設會在 Chrome 61 以上版本啟用。Firefox 正在測試 navigator.storage
,但截至 2017 年 8 月,預設並未啟用。您必須啟用 dom.storageManager.enabled
偏好設定才能進行測試。
如果您要使用某項功能,但該功能尚未在所有瀏覽器中支援,就必須進行功能偵測。您可以將功能偵測功能與以承諾為基礎的包裝函式結合,並在舊版 navigator.webkitTemporaryStorage
方法上方提供一致的介面,如下所示:
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});
}