JavaScript / 37 минут

Хранение состояния в браузере

Храните и восстанавливайте состояние с версией формата и обработкой повреждённых данных.

В процессе Теория: впереди Практика: впереди Тест: впереди
20 / 22
После этой главы
  • Храните и восстанавливайте состояние с версией формата и обработкой повреждённых данных.
  • Применить тему в задаче «Хранение состояния в браузере» и объяснить граничные случаи.

Около 7 минут на чтение и разбор примеров. Практика — отдельно, в своём темпе.

Время жизни состояния

Переменная в памяти страницы исчезает при перезагрузке. Иногда это правильно: открытый tooltip не нужно восстанавливать через неделю. Другие данные, например выбранная тема оформления, должны пережить новый запуск. Перед выбором хранилища определите владельца данных, срок жизни, объём и необходимость синхронизации между устройствами. Браузерное хранение и серверная база решают разные задачи.

localStorage сохраняет строковые пары в пределах origin и обычно переживает закрытие страницы. sessionStorage привязан к сессии вкладки со своими правилами жизненного цикла. Origin включает схему, хост и порт, поэтому localhost:3020 и localhost:3025 имеют разные локальные настройки. Сохранённое предпочтение на одном порту не обязано появиться на другом.

Строковый API и возможный отказ

getItem возвращает строку или null при отсутствии ключа. setItem записывает строковое представление. removeItem удаляет выбранный ключ. Не используйте clear ради сброса одной настройки: он затронет другие данные приложения в том же хранилище. Ключи полезно именовать с префиксом приложения и назначением, чтобы уменьшить случайные конфликты.

JavaScript
const key = 'jslab:theme';
try {
  localStorage.setItem(key, 'dark');
  const saved = localStorage.getItem(key);
  console.log(saved); // dark
} catch {
  // Интерфейс продолжает работать без сохранения предпочтения.
}

Доступ к хранилищу не гарантирован в любой среде и при любых настройках приватности. Запись может не пройти из-за ограничений или доступного объёма. Поэтому полезная настройка не должна становиться причиной полного падения интерфейса. Во время SSR браузерных объектов может не быть вообще; доступ к ним выполняют на клиентской стадии жизненного цикла.

Сериализация объектов

Для объекта можно выбрать JSON-формат. При записи JSON.stringify создаёт строку, при чтении JSON.parse разбирает её. Обе операции относятся к представлению данных, а не к проверке текущей схемы приложения. Ранее сохранённая версия, ручное изменение или другой код того же origin могут оставить строку, которая не соответствует вашим ожиданиям.

JavaScript
const settings = { version: 1, sound: true };
const raw = JSON.stringify(settings);
const restored = JSON.parse(raw);
console.log(restored.sound); // true

Не храните Date, Map или экземпляр класса в надежде автоматически получить тот же объект обратно. JSON описывает ограниченный набор данных. Для восстановления нужны явные правила, например дата как ISO-строка, Map как массив пар или доменная сущность как DTO без методов. Сначала спроектируйте формат, затем пишите адаптер чтения и записи.

Проверка формы и версия схемы

Безопасное восстановление проходит несколько стадий: проверить наличие строки, разобрать JSON, проверить тип корневого значения, затем поля и ограничения. Если ошибка ожидаемо означает повреждённые необязательные настройки, можно использовать значения по умолчанию. Если данные критичны, молчаливый сброс может быть недопустим: нужен другой сценарий восстановления и источник истины.

JavaScript
function readSound(raw) {
  if (raw === null) return true;
  try {
    const value = JSON.parse(raw);
    return value !== null && typeof value === 'object'
      && value.version === 1 && typeof value.sound === 'boolean'
      ? value.sound : true;
  } catch { return true; }
}

Поле version позволяет отличить схемы и выполнить понятную миграцию. Не нужно поддерживать бесконечное число случайных старых форматов, но обновление приложения не должно неожиданно трактовать старое число как новый объект. Явное правило миграции лучше, чем длинная цепочка неопределённых проверок с разными запасными результатами.

Синхронизация и чувствительные данные

Событие storage помогает заметить изменения из других документов того же origin. Оно не заменяет полноценную серверную синхронизацию и не гарантирует разрешения конфликтов между несколькими редакторами. Если несколько вкладок одновременно изменяют один список, заранее определите, какое обновление имеет приоритет и как избежать потери данных.

localStorage доступен JavaScript страницы. Поэтому долгоживущие секреты сессии туда обычно не помещают. Предпочтения интерфейса, черновик без чувствительных данных и кэш публичного каталога имеют другую модель риска, чем токен доступа. Данные хранилища также нельзя считать подтверждённым признаком роли или прав: сервер проверяет авторизацию независимо от состояния браузера.

Практическое восстановление массива

В задании приходит строка либо null. Корректный JSON-массив нужно отфильтровать до строковых элементов, сохранив порядок. При ошибке разбора или другом корневом типе возвращается пустой массив. Это полный маленький адаптер границы: синтаксический разбор и проверка полезных данных происходят отдельно.

Проверьте строковый массив, смешанные типы, null, повреждённый JSON и объект вместо массива. Не вызывайте filter до Array.isArray: у корректно разобранного числа такого метода нет. Для самостоятельного проекта сохраните список привычек с версией формата, а затем напишите сценарий повреждённого хранилища. Интерфейс должен показать согласованное состояние и продолжить работать без неожиданной потери чужих настроек.

Загружаем редактор…

Музыка: Reverie — Scott Buckley · CC BY 4.0