Добро пожаловать в другую статью из серии небольших и полезных функций, в которой я хотел бы показать вам аккуратную абстракцию domStorage()
, которая предоставляет набор удобных функций для взаимодействия с веб-хранилищем, а также дискретно обрабатывает все наиболее распространенные моменты неудачи.
Если вы еще не знакомы с Web Storage (он же DOM Storage), я бы порекомендовал статью Колина Ирига: обзор API Web Storage .
Вот domStorage()
функции domStorage()
:
function domStorage(persist) { try { var storage = window[persist ? 'localStorage' : 'sessionStorage']; if(!storage) { return null; } } catch(ex) { return null; } return { read : function(key) { return storage.getItem(key); } , write : function(key, value) { try { return storage[key] = value.toString(); } catch(ex) { return null; } } , erase : function(key) { storage.removeItem(key); return true; } , keys : function() { for(var keys = [], n = storage.length, i = 0; i < n; i ++) { keys.push(storage.key(i)); } return keys; } , clear : function() { try { storage.clear(); return true; } catch(ex) { return false; } } }; }
Как использовать функцию
Функция domStorage()
возвращает объект, содержащий методы, которые затем можно использовать в качестве ярлыков для таких вещей, как чтение и запись значений. Однако если веб-хранилище не поддерживается или отключено в браузере, domStorage()
возвращает значение null
. Вы начинаете с вызова domStorage()
и сохраняете возвращаемую ссылку, как показано ниже.
var storage = domStorage();
По умолчанию функция создает ссылку на хранилище сеанса — данные, которые автоматически удаляются в конце сеанса браузера. Вы также можете выбрать постоянное хранилище, передав логическое значение true
, как показано ниже. В этом случае данные будут сохраняться до тех пор, пока вы или пользователь не удалите их.
var storage = domStorage(true);
Получив ссылку на storage
, вы должны проверить, что она не равна null
прежде чем пытаться использовать ее методы:
var storage = domStorage(); if(storage !== null) { //storage is supported }
Основными методами являются read()
, который принимает один key
аргумент, и write()
, который принимает key
и value
. Взаимодействие с хранилищем происходит синхронно , поэтому вы можете прочитать значение, как только оно записано:
storage.write("key", "value"); storage.read("key");
Все сохраненные значения являются строками, причем любой другой тип данных преобразуется без вывода сообщений (например, 123
сохраняется как "123"
). Если вам нужно хранить сложные данные, лучше всего сохранить их в виде строки JSON:
storage.write("key", JSON.stringify(data));
Оба метода read()
и write()
возвращают строку в случае успеха или null
для ошибки. Ошибка read()
означает, что с этим ключом не было никакого значения хранилища, а ошибка write()
означает, что значение не было сохранено. Это произойдет только в том случае, если значение слишком велико для оставшегося доступного пространства хранения в соответствии с квотой, установленной настройками браузера, о которой мы поговорим в следующем разделе.
if(storage.write("key", "value") === null) { //value was not saved }
Есть также два метода удаления, один для удаления одного значения:
storage.erase("key");
И еще один для очистки каждого значения в объекте хранения (так что осторожно!):
storage.clear();
Наконец, есть метод keys()
который возвращает массив строковых ключей для каждого из значений, определенных в настоящее время в объекте хранения:
var keys = storage.keys();
Вы можете использовать это, например, для проверки объекта хранилища и выяснения, сколько данных оно содержит:
var size = 0, keys = storage.keys(); for(var n = keys.length, i = 0; i < n; i ++) { size += storage.read(keys[i]).length; } alert((size / 1000).toFixed(2) + 'K');
Как работает функция
По сути, все функции domStorage()
определяют набор методов ярлыков, но они также обрабатывают несколько точек отказа, которые в противном случае могли бы вызвать ошибки. Первый и, скорее всего, сбой возникает при получении ссылки на сам объект хранилища ( sessionStorage
или localStorage
соответствии с аргументом localStorage
). Объект хранилища может не поддерживаться, но даже если это так, он может вызвать ошибку при обращении к нему. Это связано с тем, что спецификация позволяет браузеру выдавать ошибку безопасности, если использование хранилища нарушает решение политики, например отключается пользователем. Итак, это первое место, где нам нужна обработка исключений, перехватывающая любую такую ошибку и возвращающую null
для сбоя:
try { var storage = window[persist ? 'localStorage' : 'sessionStorage']; if(!storage) { return null; } } catch(ex) { return null; }
Следующая потенциальная ошибка — при сохранении значения , поскольку существует ограничение на количество данных, которые мы можем хранить. Браузеры устанавливают квоту, а большинство также предоставляют пользовательские настройки для ее изменения. Насколько я знаю, нет надежного способа программного определения квоты, но обычно этого более чем достаточно — где-то от 2-5MB
, в зависимости от браузера. Если сохранение значения превысит эту квоту, браузер выдаст еще одну ошибку. Итак, мы обрабатываем это и возвращаем null
для ошибки
try { return storage[key] = value.toString(); } catch(ex) { return null; }
Вы заметите, что я использовал квадратную скобку, а не функцию setItem()
, и это просто для удобства сохранения и возврата значения в одном выражении, в качестве альтернативы этому:
try { storage.setItem(key, value); return value.toString(); } catch(ex) { return null; }
Последняя точка сбоя — при использовании функции clear()
, потому что некоторые ранние реализации не поддерживают ее (например, Firefox 3). Чтобы избежать появления ошибок в этих реализациях, мы снова используем обработку исключений, а затем возвращаем true
или false
чтобы указать успех:
try { storage.clear(); return true; } catch(ex) { return false; }
Если вам действительно нужна эта функциональность для работы в более старых реализациях, достаточно просто сделать то же самое, используя метод keys()
— перебирая возвращаемые ключи и стирая каждое значение вручную:
if(storage.clear() === false) { var keys = storage.keys(); for(var n = keys.length, i = 0; i < n; i ++) { storage.erase(keys[i]); } }
Обратите внимание, что Firefox 2-3 имеет ограниченную поддержку веб-хранилища — в дополнение к отсутствующей поддержке clear()
, они вообще не поддерживают localStorage
, только sessionStorage
. Стоит также отметить, что IE7 вообще не поддерживает веб-хранилище. IE8 поддерживает его даже в режиме совместимости, что создает ложное впечатление, что IE7 также поддерживает его.
Вывод
Что делает domStorage()
полезной абстракцией, так это то, как она обрабатывает различные точки отказа без проблем. Это избавляет от необходимости постоянно проверять, проверять и обрабатывать исключения, поэтому простые задачи, такие как чтение и запись, настолько просты, насколько и должны быть!