вкратце; доктор
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 и, возможно, некоторых изображений. Сервис-воркеры вместе с Cache Storage API предоставляют необходимую инфраструктуру для сохранения этих основных ресурсов и последующего использования их для быстрой загрузки вашего веб-приложения, в идеале полностью минуя сеть. (Инструменты, которые интегрируются с процессом сборки вашего веб-приложения, такие как новые библиотеки Workbox или более старая версия sw-precache
, могут полностью автоматизировать процесс хранения, обновления и использования данных этого типа.)
А как насчет другого типа данных? Это ресурсы, которые не нужны для загрузки вашего веб-приложения, но могут сыграть решающую роль в общем взаимодействии с пользователем. Например, если вы пишете веб-приложение для редактирования изображений, вам может потребоваться сохранить одну или несколько локальных копий изображения, чтобы пользователи могли переключаться между редакциями и отменять свою работу. Или, если вы разрабатываете автономное воспроизведение мультимедиа, сохранение аудио- или видеофайлов локально будет критически важной функцией. Каждое веб-приложение, которое можно персонализировать, в конечном итоге должно сохранять некоторую информацию о состоянии . Как узнать, сколько места доступно для такого типа хранилища среды выполнения и что произойдет, когда место закончится?
Прошлое: window.webkitStorageInfo
и navigator.webkitTemporaryStorage
Браузеры исторически поддерживали этот тип самоанализа через префиксные интерфейсы, такие как очень старый (и устаревший) window.webkitStorageInfo
и не совсем старый, но все еще нестандартный navigator.webkitTemporaryStorage
. Хотя эти интерфейсы предоставляют полезную информацию, у них нет будущего в качестве веб-стандартов.
Именно здесь на сцену выходит стандарт хранения данных WHATWG .
Будущее: navigator.storage
В рамках продолжающейся работы над Storage Living Standard несколько полезных API были добавлены в интерфейс StorageManager
, который доступен браузерам как navigator.storage
. Как и многие другие новые веб-API, navigator.storage
доступен только в защищенных источниках (обслуживаемых через HTTPS или локальный хост).
В прошлом году мы представили метод 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 года он не включен по умолчанию. Вам необходимо включить настройку 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});
}