В некоторых случаях абсолютно бессмысленно и неоправданно нагружать как клиентскую часть веб-приложения, так и серверную. Чтобы не ходить долго вокруг да около, приведу пример из жизни. От разработчика мне достался один интернет-магазин, в котором работа с корзиной происходила следующим образом. При клике на кнопку добавления товара в cookie сохранялись ID товара и его количество. Соответственно, чтобы при посещении различных страниц пользователю показывалось, что находится в корзине, в каком количестве, сколько это добро стоит и прочие данные, серверному приложению приходилось выполнять следующие функции:
Все вроде бы и ничего. Я думаю, многие с подобными схемами сталкивались и не раз. Но передо мной стояла задача оптимизации приложения, и я решил убрать среди прочего лишнюю нагрузку с сервера путем устранения как запросов в БД, так и генерацией блока корзины. Хотелось бы хранить все данные о выбранных товарах на стороне клиента. Причем, в идеале хотелось хранить не только массив выбранных товаров, но и уже готовый HTML-код блока корзины, кроме того, таблицу с товарами для страницы оформления заказа. Но как это сделать?
Ждать кроссбраузерной поддержки JavaScript с клиентским хранилищем можно еще очень долго. А использовать cookie для этой задачи нецелесообразно, как минимум потому, что длина строки в cookie весьма ограничена. Я предлагаю следующее решение в виде плагина для jQuery и небольшого дополнения к серверной части.
Таким образом, мы имеем виртуальное хранилище любых данных на стороне клиента с косвенным использованием сервера. Как это можно применить на практике?
То есть для разработчика приложения схема хранения данных абсолютно прозрачна, и ему не стоит беспокоиться о том, в каком виде и как хранить данные. В данном случае все данные объекта a перед переходом на другую страницу будут сохранены в нашем хранилище. И сразу же после открытия другой страницы данные будут занесены в объект a.
P. S. Многие могу воскликнуть, мол, зачем такая сложность, если можно оптимизировать серверную часть приложения, хранить данные сразу в сессии и отдавать тот же самый объект клиенту сразу при генерации страницы (тут вариантов масса). У меня есть ответ. Давайте представим, что мы пошли по пути оптимизации приложения, где почти все динамические страницы хранятся во временном серверном кэше в статическом HTML-виде. Кстати, если необходимо таким образом хранить более важные данные, эту схему можно «подсолить» хэш-защитой с помощью cookie.
- получение списка ID товаров из cookie;
- запрос в БД, из которой возвращалось название товара, его стоимость и прочие необходимые данные;
- использование шаблонизатора (Smarty) для генерирование блока корзины на ряду с генерацией остального содержимого.
Все вроде бы и ничего. Я думаю, многие с подобными схемами сталкивались и не раз. Но передо мной стояла задача оптимизации приложения, и я решил убрать среди прочего лишнюю нагрузку с сервера путем устранения как запросов в БД, так и генерацией блока корзины. Хотелось бы хранить все данные о выбранных товарах на стороне клиента. Причем, в идеале хотелось хранить не только массив выбранных товаров, но и уже готовый HTML-код блока корзины, кроме того, таблицу с товарами для страницы оформления заказа. Но как это сделать?
Ждать кроссбраузерной поддержки JavaScript с клиентским хранилищем можно еще очень долго. А использовать cookie для этой задачи нецелесообразно, как минимум потому, что длина строки в cookie весьма ограничена. Я предлагаю следующее решение в виде плагина для jQuery и небольшого дополнения к серверной части.
JavaScript
;(function($){
var self={
config: {
//Вызов функции после того, как все объекты будут считаны из хранилища
callback: function(){},
//Путь к серверному хранилищу
path: 'storage.php'
},
current: {
//Вызвано впервые?
first: true
},
//Само хранилище данных
storage: {},
init: function(objects,config){
if(!self.current.first)return;
self.current.first=false;
//Уст. конфиг
$.extend(self.config,config);
//Обраб. объекты
self.storage=objects;
//Восст. объекты
self.get();
$(window).unload(self.set);
$('iframe').unload(self.set);
},
//Расширяет объекты
ext: function(objects){
for(var k in objects){
if(typeof(self.storage[k])=='undefined'){
self.storage[k]={};
};
//Расширяем
if(typeof(objects[k])=='object'){
$.extend(true,self.storage[k],objects[k]);
} else {
self.storage[k]=objects[k];
};
};
},
//Возвращает объекты из хранилища
get: function(){
$.getJSON(self.config.path,function(data){
self.ext(data);
self.config.callback();
});
},
//Сохраняет в хранилище
set: function(){
$.ajax({
type: 'POST',
url: self.config.path,
data: {
storage: JSON.stringify(self.storage)
}
});
}
};
$.extend({
storage: self.init,
storageUpdate: self.set
});
})(jQuery);
PHP: storage.php
<?
session_start();
if(isset($_POST['storage'])){
$_SESSION['storage']=$_POST['storage'];
}
elseif(isset($_SESSION['storage'])){
echo $_SESSION['storage'];
}
?>
Таким образом, мы имеем виртуальное хранилище любых данных на стороне клиента с косвенным использованием сервера. Как это можно применить на практике?
var a={i:0};
$(function(){
$.storage({storageA:a},{
callback: function(){
a.i++;
alert('Вы загрузили страницу в '+a.i+'-й раз.');
}
});
});
То есть для разработчика приложения схема хранения данных абсолютно прозрачна, и ему не стоит беспокоиться о том, в каком виде и как хранить данные. В данном случае все данные объекта a перед переходом на другую страницу будут сохранены в нашем хранилище. И сразу же после открытия другой страницы данные будут занесены в объект a.
P. S. Многие могу воскликнуть, мол, зачем такая сложность, если можно оптимизировать серверную часть приложения, хранить данные сразу в сессии и отдавать тот же самый объект клиенту сразу при генерации страницы (тут вариантов масса). У меня есть ответ. Давайте представим, что мы пошли по пути оптимизации приложения, где почти все динамические страницы хранятся во временном серверном кэше в статическом HTML-виде. Кстати, если необходимо таким образом хранить более важные данные, эту схему можно «подсолить» хэш-защитой с помощью cookie.