|
| ||||||||||||
| ||||||||||||
|
2008 г.
Хранение данных на клиенте. DOM Storage и его аналогиИлья Кантор, javascript.ruНовые версии статьи публикуются на сайте автора. По мере того как web-странички превращаются в AJAX-приложения, им требуются все новые возможности. Сложные выборки элементов DOM обеспечиваются некоторыми браузерами и почти всеми распространенными Javascript-фреймворками. Кросс-доменные HTTP-запросы находят поддержку в стандартах и реализуются в новейших браузерах, включая Internet Explorer 8. В этой статье пойдет речь о средствах для хранения большого количества данных на клиенте, в браузере, которые доступны уже сейчас. В частности, Internet Explorer 5+, Firefox 2+, Safari 2+ не требуют для этого дополнительных плагинов и Flash. Зачем нужны дополнительные средства хранения?Почти во всех браузерах есть поддержка cookies. На протяжении долгого времени cookies были единственным кросс-браузерным способом сохранить данные, которые будут доступны после перезагрузки страницы. Однако у cookie есть две важных особенности:
Средства хранения на клиенте предусматривают сотни килобайт и мегабайты данных, и не отсылают их на сервер при каждом HTTP-запросе. А cookie можно продолжать использовать, например, для хранения сессии. Firefox (Gecko). Стандарт HTML 5.Firefox реализует стандарт хранения "Client-side session and persistent storage of name/value pairs", предложенный в спецификации HTML 5. Для постоянного хранения данных в нем используется объект Например: storage = globalStorage[document.domain]
// записать значение
storage['userName'] = 'Vasya'
// прочитать значение
alert(storage['userName'])
// удалить значение
delete storage['userName']
// получить все значения
for(var name in storage) {
alert(name + ':' + storage[name])
}
При чтении/записи на элементе Поймать его можно, например, таким обработчиком: window.addEventListener('storage', function(event) { ... })
Стандарт HTML 5 все еще в процессе развития. В старой редакции прочитанные значения имели тип Версия Firefox 2.0.0.13 возвращает при чтении объект именно этого типа. Из текущей редакции ..А пока эти изменения не учтены разработчиками, рекомендуется преобразовать значения к Например: var test = "12345" storage.test = test // сохранить -> String test = storage.test // прочитать <- StorageItem alert(test.length) // undefined, это же не строка alert(test.constructor) // StorageItem test = String(test) // сделали строку. Теперь все ок. ОграниченияОграничения на данные: ключи и значения - только строки. Размер: 5MB на домен. Ограничения безопасности - точно такие же, как на cookie. Дополнительные материалыInternet Explorer. userData.Internet Explorer 8 реализует DOM Storage, в то время как версии начиная от 5й поддерживают собственный интерфейс: userData behavior. Он работает посредством выделенного DOM-элемента, которому назначается behavior userData. В этот элемент загружается нужное пространство имен, и данные становятся доступны через атрибуты. <span id="storageElement"></span>
<script>
storage = document.getElementById('storageElement')
if (!storage.addBehavior) {
alert("userData not available.")
} else {
// поставить userData behavior
storage.addBehavior("#default#userData")
// загрузить пространство имен
storage.load("namespace")
}
</script>
После инициализации можно работать с данными. Для записи изменений используется метод save.
function put(key, value) { // записать значение
storage.setAttribute(key, value)
storage.save("namespace")
}
function get(key) { // получить значение
return storage.getAttribute(key)
}
function remove(key) { // удалить значение
storage.removeAttribute(key)
storage.save("namespace")
}
Как это часто бывает с Internet Explorer, некоторые операции делаются неочевидным :) образом. Так, например, получить все сохраненные данные из Данные же хранятся в свойстве Например, следующий код создает список вида ключ:значение. var list = []
var attrs = storage.XMLDocument.documentElement.attributes
for(var i=0; i<attrs.length; i++) {
list.push(attrs[i].name+':'+attrs[i].value);
}
Устаревание, атрибут expiresВ отличие от DOM Storage, можно задать атрибут var time = new Date(); // Start Time time.setMinutes(time.getMinutes() + 1) storage.expires = time.toUTCString(); Устаревание, атрибут expires
В отличие от DOM Storage, можно задать атрибут var time = new Date(); // Start Time time.setMinutes(time.getMinutes() + 1) storage.expires = time.toUTCString(); ОграниченияКлючи и значения - только строки. Способ работает при всех уровнях безопасности, кроме "Высокого". Ограничения безопасности - та же директория, тот же домен и протокол. Дополнительные материалыSafari(WebKit). Database storage.Дальше всех в поддержке стандарта хранения пошли разработчики WebKit. Набор операций включает в себя CREATE TABLE, INSERT, SELECT, REPLACE, индексы и многое другое, с рядом ограничений безопасности (например, нет LOAD DATA INFILE). В отличие от DOM Storage и userData, этот интерфейс асинхронный. Все
функции запросов к базе данных принимают в качестве аргументов две
функции: Когда запрос завершается, вызывается один из этих обработчиков. Продемонстрируем это на тестовой базе. db = openDatabase("Test", "1.0", "Webkit Storage Example")
db.transaction(function(tx) {
tx.executeSql(
"CREATE TABLE IF NOT EXISTS test (key TEXT, value TEXT, unique(key))",
[],
function(tx, result) { alert("Success!") },
function(tx, error) { alert("Failure: "+error.message }
)
})
Сложновато с первого взгляда?
Код внутри Вызов
Следующий пример демонстрирует обработку запроса. db.transaction(function(tx) {
tx.executeSql("SELECT value FROM test WHERE key=?", [key],
function(tx,result) {
alert("Количество результатов: "+result.rows.length)
alert("Поле value первого результата: "+ result.rows.item(0).value)
},
function(tx, error) { alert("Error!") }
)
})
ОграниченияСтандарт SQL-хранения также включает в себя поддержку версий схемы, указание размера базы данных в База существует только в рамках домена(полного домена, origin), на котором была создана. Поддомен не имеет доступа к базе домена. Дополнительные материалыНа момент написания статьи разработчики WebKit планировали поддержку DOM Storage, но в nightly build ее не было. OperaНа момент написания статьи Opera 9.5 (beta) не поддерживает ни DOM Storage ни Database Storage. С другой стороны, разработчики планируют эту поддержку включить. Flash. SharedObject.Там, где нет DOM Storage, для offline-хранения используют flash-интерфейс Пример ActionScript для работы с // создать/получить namespace storage
storage = SharedObject.getLocal("storage");
// записать данные name => Вася
storage.data.name="Вася";
// сохранить объект
storage.flush()
// перечислить свойства объекта
for (var name in storage.data) {
trace(name + ":" + storage.data[name])
}
Чтобы работать с этим хранилищем из javascript, нужен способ коммуникации JS <->Flash. В старых версиях Flash вызвать javascript можно через Передать значение во Flash можно установкой переменной flash-объекту. Эту переменную flash-ролик может считывать каждый кадр и предпринимать соответствующие действия. Во Flash 8+ появился интерфейс Код примера в ActionScript: import flash.external.*;
// установить местную функцию recieveFromJS для приема данных
// от javascript-функции sendFromJS
ExternalInterface.addCallback("sendFromJS", null, recieveFromJS);
// Эта функция будет реагировать на sendFromJS
function recieveFromJS(text) {
_root.theText.text = text; // .. и устанавливать текст в окошке
}
// Это действие, наоборот, отправляет данные в JS.
_root.button.onRelease = function() {
// вызвать javascript-функцию recieveFromFlash
ExternalInterface.call("recieveFromFlash", _root.theText.text);
_root.theText.text = "";
}
Код примера в JS: function recieveFromFlash(Txt) {
document.getElementById('text').value = Txt;
}
function sendFromJS() {
var value = document.getElementById('text').value
var movie = (navigator.appName.indexOf("Microsoft")!=-1 ? window : document)["BridgeMovie"]
movie.sendFromJS(value);
document.getElementById('text').value = ''
}
Скачать исходники
Документация на ExternalInterface Особенности и ограниченияДоступ к SharedObject ограничен роликами с того же домена. Это принципиально отличается от Javascript, в котором доступ определяется адресом страницы а не скрипта, и делает возможным разного рода кросс-доменные трюки. Ограничение по умолчанию на размер данных - в районе 100Kb, пользователь может уменьшить или увеличить его в специальном Flash-интерфейсе, который открывается при вызове ActionScript: System.showSettings(1); Проблемы реализацииВо-первых, надо иметь Flash. Хранилище доступно только после инициализации Flash-ролика. Много ошибок в различных версиях Flash затрагивают ExternalInterface, включая повреждение данных во время передачи JS->Flash. Проще всего узнать о них: Много работы над обходом багов провел Brad Neuberg для flash-хранилища в dojo:
Резюме.DOM Storage и аналогичные системы хранения - важный шаг к offline-работе web-приложений. В браузере Opera все еще приходится использовать Flash Shared Object, а Firefox, Internet Explorer, Safari реализуют хранилище без дополительных плагинов и Flash<->JS коммуникации. Интересным сектором для интеграции могут быть CRM-системы с нестабильным интернетом. Например, мини-точка продаж, в которой основная работа идет через интеренет, но хранение текущих договоров дублируется на рабочей машине. Offline-хранилище может быть использовано для сохранения сложных состояний интерфейса - размеров окон, контрольных элементов и т.п. Все изменения интерфейса посетителем мгновенно сохранятся в DOM Storage и восстановятся при следующем заходе на страницу без дополнительных механизмов сохранения интерфейса на сервере. При этом объем хранимого состояния интерфейса вряд ли превысит ограничение в сотни килобайт. Идеальный объект для DOM Storage, не правда ли ?.. Об авторе: Илья Кантор, в разработке интернет-приложений с 1999 года. Начиная с 2003 года разрабатывает клиентские интерфейсы и сложные поисковые структуры для баз данных. В свободное время поддерживает полезные ресурсы, посвященные алгоритмам и методам программирования и разработке на клиенте: Firebug, XmlHttpRequest и др. |
|
CITForum © 1997–2025