TypeScript и StorageManager

TypeScript и StorageManager

В этой статье объясняются TypeScript и StorageManager.

Мы предлагаем практические примеры для объяснения TypeScript и StorageManager.

YouTube Video

TypeScript и StorageManager

Что такое StorageManager?

StorageManager — это API, позволяющее веб-приложениям оценивать, сколько места используется и сколько доступно в хранилище. Он также предоставляет возможность запроса постоянного хранения данных (persist()), чтобы предотвратить их автоматическое удаление пользователем или браузером. Это позволяет контролировать, достаточно ли свободного места или будут ли данные автоматически удалены, например при хранении больших объемов данных в IndexedDB для офлайн-приложений.

Обнаружение поддержки функций

Сначала проверьте, поддерживает ли браузер navigator.storage.

 1// TypeScript: feature detection for StorageManager
 2function supportsStorageManager(): boolean {
 3  return typeof navigator !== "undefined" &&
 4         typeof navigator.storage !== "undefined" &&
 5         typeof navigator.storage.estimate === "function";
 6}
 7
 8// Example usage
 9if (supportsStorageManager()) {
10  console.log("StorageManager is supported.");
11} else {
12  console.warn("StorageManager not supported. Falling back to localStorage or IndexedDB.");
13}
  • Эта функция поэтапно проверяет доступность StorageManager API.
  • Поскольку navigator.storage отсутствует в некоторых браузерах, например, Safari, важно безопасно проверять его наличие с помощью typeof.

Оценка использования хранилища (estimate())

После проверки наличия функционала с помощью supportsStorageManager(), получите использование (usage) и квоту (quota) из navigator.storage.estimate().

 1// TypeScript: safely get storage estimate
 2async function getStorageEstimate(): Promise<{ usage: number; quota: number } | null> {
 3  if (!supportsStorageManager()) {
 4    console.warn("StorageManager not supported.");
 5    return null;
 6  }
 7
 8  const estimate = await navigator.storage.estimate();
 9  return { usage: estimate.usage ?? 0, quota: estimate.quota ?? 0 };
10}
11
12// Example usage
13getStorageEstimate().then(result => {
14  if (result) {
15    console.log(`Usage: ${result.usage} bytes / Quota: ${result.quota} bytes`);
16  }
17});
  • Эта функция всегда работает безопасно и возвращает null, если браузер её не поддерживает.
  • usage и quota представляют собой оценки и могут различаться в разных браузерах.

Запрос на постоянное хранение данных (persist())

Используйте persist() для запроса постоянного хранения данных, чтобы важные данные (например, офлайн-кэш) не удалялись автоматически браузером. Однако это не срабатывает во всех средах.

 1// TypeScript: safely request persistent storage
 2async function requestPersistence(): Promise<boolean> {
 3  if (!supportsStorageManager()) {
 4    console.warn("StorageManager not supported.");
 5    return false;
 6  }
 7
 8  if (typeof navigator.storage.persist !== "function") {
 9    console.warn("persist() not available in this browser.");
10    return false;
11  }
12
13  try {
14    const granted = await navigator.storage.persist();
15    return Boolean(granted);
16  } catch (err) {
17    console.error("persist() error:", err);
18    return false;
19  }
20}
21
22// Example usage
23requestPersistence().then(granted => {
24  console.log("Persistence granted?", granted);
25});
  • Если persist() выполняется успешно, данные не будут автоматически удаляться браузером, кроме случаев ручного удаления пользователем. Тем не менее, запросы могут быть отклонены в зависимости от действий пользователя или настроек браузера.

Проверьте доступное место перед сохранением данных

Проверьте доступное место перед сохранением больших данных, чтобы предотвратить ошибки записи (QuotaExceededError).

 1// TypeScript: ensure enough space before writing
 2async function ensureSpaceAndWrite(neededBytes: number, writeFn: () => Promise<void>): Promise<boolean> {
 3  const estimate = await getStorageEstimate();
 4  if (!estimate) {
 5    console.warn("Cannot check storage space. Proceeding without validation.");
 6    await writeFn();
 7    return true;
 8  }
 9
10  const free = estimate.quota - estimate.usage;
11  if (free < neededBytes) {
12    console.warn(`Not enough space. Free: ${free} bytes, needed: ${neededBytes} bytes.`);
13    return false;
14  }
15
16  await writeFn();
17  return true;
18}
19
20// Example usage
21ensureSpaceAndWrite(10 * 1024 * 1024, async () => {
22  console.log("Saving large data...");
23});
  • Проверяя доступное хранилище перед сохранением, вы уменьшаете риск прерывания записи из-за нехватки места.

Безопасная по типам работа с localStorage в TypeScript

localStorage удобен для хранения легких данных конфигурации и аналогичной информации.

Следующий класс использует дженерики для создания безопасной по типам обертки.

 1// TypeScript: typed localStorage wrapper
 2type Serializer<T> = {
 3  serialize: (v: T) => string;
 4  deserialize: (s: string) => T;
 5};
 6
 7class TypedLocalStorage<K extends string, V> {
 8  constructor(private storage: Storage, private serializer: Serializer<V>) {}
 9
10  set(key: K, value: V): void {
11    this.storage.setItem(key, this.serializer.serialize(value));
12  }
13
14  get(key: K): V | null {
15    const raw = this.storage.getItem(key);
16    if (raw === null) return null;
17    try {
18      return this.serializer.deserialize(raw);
19    } catch {
20      return null;
21    }
22  }
23
24  remove(key: K): void {
25    this.storage.removeItem(key);
26  }
27
28  clear(): void {
29    this.storage.clear();
30  }
31}
32
33// Example usage
34const jsonSerializer: Serializer<any> = {
35  serialize: v => JSON.stringify(v),
36  deserialize: s => JSON.parse(s),
37};
38
39const appStorage = new TypedLocalStorage<'theme' | 'token', any>(localStorage, jsonSerializer);
40appStorage.set('theme', { dark: true });
41console.log(appStorage.get('theme'));
  • Этот класс помогает уменьшить риск хранения или извлечения данных неверного типа.

Практические замечания и лучшие практики

  • Всегда проверяйте, поддерживает ли браузер StorageManager Поскольку StorageManager — сравнительно новый API, всегда проверяйте его наличие перед использованием.

  • Обращайте внимание на лимиты хранилища и совместимость Значение, возвращаемое estimate(), зависит от браузера и представляет собой оценку.

  • Проектируйте с учетом асинхронных API estimate() и persist() — это асинхронные API на основе промисов. Строьте свой код так, чтобы не блокировать пользовательский интерфейс.

  • Соображения безопасности Не храните чувствительную информацию, такую как токены доступа, в localStorage. Рассмотрите возможность использования HttpOnly cookie или шифрования, если это возможно.

  • Резервная архитектура Если supportsStorageManager() возвращает false, реализуйте логику переключения только на localStorage или IndexedDB.

Резюме

Благодаря обнаружению возможностей с помощью supportsStorageManager(), вы можете безопасно поддерживать все среды, проверять использование и квоты через navigator.storage.estimate(), а также запрашивать постоянное хранение с помощью persist(). В TypeScript используйте обертки и определения типов для написания читаемого и безопасного кода. Основной процесс: проверка наличия, оценка, запрос постоянного хранения и проверка емкости перед записью в хранилище.

Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.

YouTube Video