Использование HTML5 хранилища

Автор: Евгений Рыжков и Татьяна Головко Дата публикации: 28.03.2011

HTML5 хранилище основано на парах ключ/значение. Ты можешь сохранить какие-то данные под каким-то именем, а затем извлечь эти данные по этому имени:

interface Storage {
	getter any getItem(ключ в DOMString);
	setter creator void setItem(ключ в DOMString, любой тип данных);
};

Имя ключа — это строка. Сохраняемые данные могут быть любого типа поддерживаемого Javascript, включая строки, логические, целочисленные и дробные. Однако в реальности данные хранятся в виде строки. Если тебе нужно, чтобы извлекаемые данные были в каком-то другом типе, тогда используем для этого специальные Javascript функции, вроде parseInt() или parseFloat().

Вызов setItem() с именем ключа, который уже существует, приведет к перезаписи значения. Вызов getItem() с несуществующим именем вернет null.

Как и к другим объектам Javascrpt, к localStorage можно обращаться как к ассоциативному массиву. Вместо использования методов getItem() и setItem() с круглыми скобками, можно использовать квадратные. Например, этот код:

var foo = localStorage.getItem("bar");
// ...
localStorage.setItem("bar", foo);

может быть перезаписан с использованием квадратных скобок:

var foo = localStorage["bar"];
// ...
localStorage["bar"] = foo;

Есть также методы для удаления данных по имени ключа и очистки всего хранилища (т.е. удаление всех значений одновременно).

interface Storage {
	deleter void removeItem(ключ в DOMString);
	void clear();
};

В результате вызова removeItem() с несуществующим ключом ничего не произойдет.

Наконец, есть свойство, которое вернет общее число значений в хранилище, а также способ организовать итерацию перебора всех значений:

interface Storage {
	readonly attribute unsigned long length;
	getter DOMString key(in unsigned long index);
};

Если ты вызовешь key() с индексом, который будет вне предела 0 и (length-1), функция вернет null.

Отслеживание изменений в локальном хранилище.

Если тебе требуется отследить программно изменения в локальном хранилище, тебе потребуется событие storage. Это событие генерируется для объекта window, во время вызова setItem(), removeItem() или clear() и срабатывает только во время реальных изменений содержимого хранилища. Например, если ты установил уже существующее значение или очистил пустое хранилище, то состояние хранилища не изменилось и событие storage не сработает.

Событие storage поддерживается везде, где поддерживается объект localStorage (включая даже IE8). IE8 не поддерживает W3C стандарт addEventListener, поддержку которого обещают в IE9. Поэтому, чтобы отловить изменение состояния хранилища, сперва нужно понять, какой механизм поддерживает браузер. Перехват события storage работает так же как и для любого другого события:

if (window.addEventListener) {
	window.addEventListener("storage", handle_storage, false);
} else {
	window.attachEvent("onstorage", handle_storage);
};

Вызов функции handle_storage() происходит с объектом StorageEvent, кроме Interner Explorer, где объект события хранится в window.event.

function handle_storage(e) {
	if (!e) { e = window.event; }
}

Переменная e будет объектом StorageEvent, обладающая полезными свойствами:

Свойство Тип Описание
key String Имя ключа, который был добавлен, удален или изменен
oldValue Any Предыдущее значение в момент перезаписи или null в момент добавления новой.
newValue Any Новое значение (во время добавления или изменения) или null в момент удаления.
url* String Страница которая вызвала метод, который привел к изменениям в хранилище

* — свойство URL изначально называлось URI, и некоторые браузеры так и продолжают это называть. Для максимальной совместимость нужно проверить поддержку свойства URL и если ее нет, подставить URI.

Произошедшие изменения в хранилище отменить нельзя. Событие storage — это просто способ оповестить разработчика, что изменение случилось.

Ограничения в распространенных браузерах

Когда я описывал краткую история хаков для реализации локального хранилища, упоминал об ограничениях каждого. Но я ничего еще не писал об ограничениях хранилища по стандартам HTML5.

По умолчанию каждый ресурс получает в свое распоряжение 5Mb. На удивление все браузеры придерживаются этой цифры, хотя она в спецификации представлена в виде предложения. Так же следует помнить, что данные хранятся только в строковом виде, а не оригинальном формате, что не всегда удобно.

Если превысишь квоту хранилища, получишь исключение "QUOTA_EXCEEDED_ERR". Ответом на вопрос «могу ли я попросить пользователя увеличить объем хранилища?» будет «нет». На момент написания книги, браузеры не предоставляли подобные механизмы для разработчиков. Некоторые браузеры, например Opera, дают возможность контролировать объем хранилища для каждого сайта. Но только по инициативе самого пользователя.

Куда дальше