Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Работа с локальным хранилищем, как с объектом (https://javascript.ru/forum/project/28192-rabota-s-lokalnym-khranilishhem-kak-s-obektom.html)

FINoM 10.05.2012 21:18

Работа с локальным хранилищем, как с объектом
 
http://habrahabr.ru/post/143597/
Выношу на обсуждение своё небольшое изобретение для тех, кого нет на хабре и для тех, кого харит там комментировать. Здесь хотя-бы можно нормально обосрать, не боясь слива.

vadim5june 10.05.2012 22:16

Из за наличия таймера с таким объектом нужно работать специфически например насколько я понимаю его в цикл нельзя вставить

FINoM 10.05.2012 22:19

Цитата:

Сообщение от vadim5june
Из за наличия таймера с таким объектом нужно работать специфически например насколько я понимаю его в цикл нельзя вставить

Присваивать — да, в цикле не желательно. А вот получать значения вполне можно.

FINoM 10.05.2012 22:21

А хотя, чего бы нет? Взять объект, поработать с ним в цикле, а затем, после всех операций, присвоить.

devote 10.05.2012 22:33

мда, вариант интересный но не годный, например такой способ не вызовет геттер и вся твоя реализация идет прахом:
objectLocalStorage = { a: 4, b: {c: 2} };
var b = objectLocalStorage.b;
b.c = 10;
alert( objectLocalStorage.b.c ); // alert 2
Я делал что-то подобное, но отказался от этого решения из-за этого недостатка.

FINoM 10.05.2012 22:43

devote, угу, я внизу указал на это. Думаю, решение найти можно, но оно будет очень тяжелым. То есть для каждого ключа каждого подобъекта добавить геттер и хранить это всё как-нибудь.

С другой стороны, с этим объектом можно поработать, а затем присвоить туда, откуда взял. Всё же некоторая оптимизация.

FINoM 11.05.2012 03:31

Идея — говно :D
Цитата:

Несмотря на количество плюсов, которое больше нуля и количеству пользователей, добавивших статью в избранное (на текущий момент 71), считаю идею провальной и не пригодной для крупных проектов с большими объемами данных. Кроме кучи очевидных минусов, описанных в статье, есть менее очевидный минус, касающийся производительности. Каждый раз, когда вы запрашиваете или меняете данные в объекте-хранилище, вызывается стрингификация объекта, затем проверка, равна ли полученная строка значению из localStorage, затем, если проверка вернула ложь, строка отправляется в localStorage. Если какой-либо элемент объекта хранилища перебирать в цикле, эта операция будет происходить на каждой итерации, даже если банально инкрементируется какое-нибудь число из объекта.

Предлагаю относиться к этой статье, как к некоему эксперименту, никак не упрощающему веб разработку и, при повседневном использовании идущем ей во вред.

Gvozd 11.05.2012 03:57

Цитата:

Сообщение от FINoM
есть менее очевидный минус, касающийся производительности.

Так не покатит?
if(timer == null) {
            timer = setTimeout( function(){
                var stringified = JSON.stringify( _objectLocalStorage );
                // некое подобие оптимизации: если данные в объекте не изменились,
                // значит присваивания никакого не было, сработал обычный гет
                if( stringified !== localStorage.getItem( 'objectStorage' ) ) {
                    // сохраняем 
                    localStorage.setItem( 'objectStorage', stringified );
                }
                timer = null;
            }, 0);
        }

FINoM 11.05.2012 04:27

Цитата:

Сообщение от Gvozd
Так не покатит?

Дай-ка подумать... Значит, во-первых, не вызывается этот кошмар при каждой итерации, во-вторых, не будет «перебоя» новых данных старыми, что являлось следствием асинхронности. Вариант. Очень даже не плохой, на сонную голову.

devote 11.05.2012 04:29

Цитата:

Сообщение от Gvozd
if(timer != null) {

дык может не != а все же ==
не?

Gvozd 11.05.2012 04:30

Цитата:

Сообщение от devote
дык может не != а все же ==
не?

вы правы

FINoM 11.05.2012 04:34

Цитата:

Сообщение от devote
дык может не != а все же ==
не?

Пофиг, главное мысль понятна :)

FINoM 29.05.2012 22:29

var Storage = function Storage ( name, duration ) {
	this._name = name || this._name;
	this._duration  = duration || this._duration;
	this._init();
}

Storage.prototype = {
	_name: '_nameOfYourSrorage',
	_duration: 5000,
	// type == local || session
	_save: function( type ) {
		window[ type + 'Storage' ].setItem( this._name, JSON.stringify( this[ type ] ) );
	},
	
	_get: function( type ) {
		this[ type ] = JSON.parse( window[ type + 'Storage' ].getItem( this._name ) ) || {};
	},
	 
	_init: function() {
		var self = this;
		self._get( 'local' );
		self._get( 'session' );
		
		( function callee() {
			setTimeout( function() {
				self._save( 'local' );
				callee();
			}, self._duration );
		})();
		
		window.addEventListener( 'beforeunload', function() {
			self._save( 'local' );
			self._save( 'session' );
		} );
	},
	
	local: {},
	session: {}
};
Вот самый адекватный и производительный вариант использования хранилища, как объекта. Взял из своего проекта, может быть кому-то будет полезным.
var storage = new Storage;
storage.local = {a:4, b: {c:5}};
storage.session = {a:7, b: {c:8}};
b = storage.local.b;
b.c = {d:6};

Стоит объяснять что к чему?

Раед 29.05.2012 22:36

FINoM,
Гениально! Просто, удобно (никакой асинхронности). Спасибо:thanks:

melky 29.05.2012 22:38

FINoM, видел ваш пост на хабре.

жаль, что вы про IE забыли :( там ведь чуточку сложнее, и все по-другому. но использование одинаковое.

FINoM 29.05.2012 22:39

Цитата:

Сообщение от Раед
(никакой асинхронности)

Вон Гвоздь показал, как убрать асинхронность. Но решение всё равно осталось очень тяжелым и неудобным.
А этот вариант на хабре предложили, моя заслуга здесь только в нескольких строках кода.

FINoM 29.05.2012 22:40

Цитата:

Сообщение от melky
жаль, что вы про IE забыли

В посте? Не стоит его воспринимать всерьез. Решение плохое.

Раед 29.05.2012 22:51

Цитата:

Сообщение от FINoM
Не стоит его воспринимать всерьез. Решение плохое.

Почему?

FINoM 29.05.2012 23:06

Цитата:

Сообщение от Раед
Почему?

При любом запросе чего-либо из хранилища, происходит стрингификация объекта и сохранение в localStorage.
objectLocalStorage.a ← вызовет эту сложную операцию.
Кроме этого,
objectLocalStorage.a.b = 5; // сработает
a = objectLocalStorage.a;
a.b = 5; // не сработает

Раед 29.05.2012 23:13

FINoM,
Мы с вами кажется про разные посты говорим. Я про этот, а вы про этот

FINoM 29.05.2012 23:16

Цитата:

Сообщение от Раед
FINoM,
Мы с вами кажется про разные посты говорим. Я про этот, а вы про этот

А, ну я непонятно выразился. http://javascript.ru/forum/177411-post13.html — это решение единственное нормальное, на сегодняшний день.

Gozar 31.05.2012 00:42

Шота меня setTimeout дюже смущает, в виду возможности вселенских масштабов утечек связанных с ним.

Раед 31.05.2012 01:58

Цитата:

Сообщение от Gozar
Шота меня setTimeout дюже смущает, в виду возможности вселенских масштабов утечек связанных с ним.

Да там вроде ничего не мешает его убрать

GuardCat 31.05.2012 15:08

Цитата:

Сообщение от Gozar
Шота меня setTimeout дюже смущает, в виду возможности вселенских масштабов утечек связанных с ним.

Я буквально вчера смотрел на что способен setTimeout по ресурсопотреблению. Выложил в блоге. Делал на коленке и результаты предсказуемы, но вдруг окажется полезно.

Deff 31.05.2012 15:53

Цитата:

Сообщение от GuardCat
Выложил в блоге.

:) А как на счет setInterval ?

GuardCat 31.05.2012 15:56

Deff, стараюсь не пользоваться, потому и не проверял.

Deff 31.05.2012 15:59

GuardCat,
У мну подозрение - что - поменее, а использование таково: - засылать периодически запросы на сервак - нет ли новых данных - (Была задачка в компутерном киоске на улице

GuardCat 31.05.2012 16:09

Deff, может проще тогда в callback запроса вставить следующий запрос по setTimeout? Тогда и ошибку можно обработать и не получится такого, что запрос пытаемся повторить до того, как пришёл ответ на предыдущий? Гибче setTimeout.

devote 31.05.2012 16:09

GuardCat,
браузеры при использовании чего либо отъедают память и тестить смотря в диспетчер задач нет смысла. Так как там всегда разные цифры, никогда не бывают одни и те же.

GuardCat 31.05.2012 16:14

Цитата:

Сообщение от devote
Так как там всегда разные цифры, никогда не бывают одни и те же

devote, разумеется, но ведь есть же общие тенденции? Например, всегда памяти расходуется больше после установки таймера и всегда часть её высвобождается после отработки таймера. Ну как всегда. Не было получено иных результатов в ходе тестов...

Deff 31.05.2012 16:51

Цитата:

Сообщение от GuardCat
Deff, может проще тогда в callback запроса вставить следующий запрос по setTimeout? Тогда и ошибку можно обработать и не получится такого, что запрос пытаемся повторить до того, как пришёл ответ на предыдущий? Гибче setTimeout.

Хм - а чем плоха проверка флага, (установленного callback возможного ответа) в запущенной setInterval функции, там можно и новый запрос прицепить, в зависимости от флага? - у мну ощущение, что все таки один setInterval меньше жрёт чем несколько setTimeout.

Gozar 31.05.2012 19:18

Цитата:

Сообщение от GuardCat
Например, всегда памяти расходуется больше после установки таймера и всегда часть её высвобождается после отработки таймера.

Память может не успеть высвободится прежде чем приложение рухнет вместе с браузером.

Я привести тест(визуализация действий пользователя в админке) не могу, слишком сложно его воспроизводить, но у меня первая упала Опера 12, затем Firefox12 и затем Chrome 7-19 из-за того что setTimeout сожрал всю память.

Твой тест не сильно поможет при создании сложного приложения, которое работает больше 20 минут. Я такие тесты вообще перестал делать. Тестирую часами, по 8 - 12 часов. К сожалению не знаю как сделать это по другому, но возможно, что никто не знает.

Deff 31.05.2012 19:27

GuardCat,
Ну у мну запрос отправлялся раз в час, быстрее данные не обновлялись, ксать как то работало с неделю без перезагрузки.. Хотя я рекомендовал раз в день, Да браузер был Гугол Хром

GuardCat 31.05.2012 22:40

Gozar, да, я понимаю, что запускать новый gmail, руководствуясь моим опытом, не стоит =)

Опыт с 8--12 часами работы приложения можно приблизить к реальности, наняв гастарбайтера и предложив ему понажимать всё подряд на экране в течение этого времени =)

Gozar 01.06.2012 00:10

Цитата:

Сообщение от GuardCat
я понимаю, что запускать новый gmail, руководствуясь моим опытом, не стоит =)

Почему? Как ты собираешься получить нужный тебе опыт, если он тебе конечно нужен?

GuardCat 01.06.2012 06:13

Gozar, говоря "мой опыт", я подразумеваю опыт в смысле "эксперимент". Я про это своё исследование setTimeout.

Да и js в данный момент для меня просто хобби, а не область профессиональных интересов.

GuardCat 01.06.2012 13:58

Deff, вот поэтому я избегаю использовать setInterval, предпочитая многократный setTimeout.

Gozar 01.06.2012 14:35

Цитата:

Сообщение от GuardCat
js в данный момент для меня просто хобби, а не область профессиональных интересов.

Что не мешает и не противоречит одно другому.

Я говорил немного о другом. Скорее о том, что при использовании долгоиграющих функций и setTimeout входит в их число очень легко наступить на грабли, даже не подозревая об этом.

Ух ты у меня карма 166. Похоже сегодня Пятница 13 по Чучхенскому календарю. :blink:

B~Vladi 01.06.2012 14:43

Прелесть использования setTimeout ещё и в том, что время задержки можно корректировать при каждом следующем запуске функции, в зависимости от того, на сколько задержался предыдущий таймер.

Суммарное время таймеров при этом будет правильным настолько, насколько это вообще возможно в браузере.

Это хорошо видно при анимации: если произошел лаг (а это частое явление) - следующий шаг будет уже больше, уменьшая время, оставшееся до конца анимации. И это правильно.

Deff 01.06.2012 15:27

Цитата:

Сообщение от B~Vladi
Прелесть использования setTimeout

Cобственно Спорный довод, посколь существует
clearInterval, и перезапуск, и У мну жуткое подозрение что setTimeout и
setInterval формируются одинаково, ток у setTimeout стоит однократный флаг исполнения завершающий функцию, очевидно, еще и чистит дефолтное или установленное Timerid


Часовой пояс GMT +3, время: 21:48.