Работа с локальным хранилищем, как с объектом — Продолжение

в 18:36, , рубрики: javascript, localStorage, sessionstorage, storage, Веб-разработка

Этим постом я бы хотел исправиться и предложить адекватный способ работы с хранилищем, как с объектом. Код из поста «Работа с локальным хранилищем, как с объектом? Легко!» использовать крайне не рекомендую, там всё плохо (минусы изложены внизу). Цель данного — объяснить всем тем, кто добавил статью по ссылке в избранное или поставил плюсик, никогда не использовать этот код.

Сейчас же я хочу продемонстрировать проетейшую идею, предложенную Scalar в комментарии.

При загрузке страницы (даже до события готовности DOM дерева) обращаемся к хранилищу (в данном случае, это localStorage и sessionStorage), получить JSON, десериализовать его и положить в какую-нибудь переменную.

localObject = JSON.parse( localStorage.getItem( '_myStorage' ) ); // "{'a':1, 'b':2}" → {a:1, b:2}

Затем, каждые N миллисекунд производить обратный процесс:

localStorage.setItem( '_myStorage', JSON.stringify( localObject ) );

При событии onbeforeunload делать то же самое.

Реализация идеи слишком проста (уровень сложности реализации низок и доступен даже новичку). Но, не все (и я в том числе) до этого додумались.

Код конструктора ObjectStorage

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

ObjectStorage.prototype = {
	_name: '_objectStorage',
	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 ObjectStorage;
storage.local = {a:4, b: {c:5}};
storage.session = {a:7, b: {c:8}};
b = storage.local.b;
b.c = {d:6};


Перезагружаете страницу,

var storage = new ObjectStorage;
console.log( storage );
/* 
{
	_name: ..., duration: ...,
	local: {a:4, b: {c: {d: 6}}},
	session: {a:7, b: {c :8}}
}
*/

Как вариант, при вызове конструктора ObjectStorage, можно передать два аргумента: name — имя ключа в хранилище и duration — интервал сохранения данных в localStorage.

new ObjectStorage( '_myStorage', 1000 );

Можно оставить имя из прототипа:

new ObjectStorage( null, 1000 );

А можно и после инициализации изменить duration:

var storage = new ObjectStorage;
storage.duration = 2000;

(можно и storage._name изменить, но это не рекомендуется, для этого даже палочку поставил, типа приватное свойство :))

Плюсы, по сравнению с решением по ссылке в начале этой статьи:

  • Производительность: нет никаких геттеров, не нужно каждый раз при вызове ключа дёргать хранилище.
  • Компактность.
  • Можно работать как с обычным объектом:
    storage.local = {a:{}}
    storage.local.a.b = 5; // сработает
    a = storage.local.a;
    a.b = 5; // и так сработает
    
  • Встроенное решение для sessionStorage.

Общие минусы:

  • Если браузер закроется некорректно (БСОД, отключение электричества и пр.) можно потерять (о боги!) работу за последне M секунд (по умолчанию, пять). Сколько я ни старался придумать сценария, где этот момент критичен, не смог

Автор: Finom

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js