Working with local storage as an object - Continued

  • Tutorial
With this post I would like to correct and offer an adequate way to work with the repository, as with an object. Code from the post “ Working with local storage, as with an object?” Easy! "I highly recommend not using it, everything is bad there (the minuses are outlined below). The purpose of this is to explain to all those who added the article by reference to favorites or put a plus sign to never use this code .

Now I want to demonstrate the simplest idea proposed by Scalar in a comment .

When the page loads (even before the DOM tree readiness event) we access the repository (in this case, localStorage and sessionStorage), get JSON, deserialize it and put it in some variable.
localObject = JSON.parse( localStorage.getItem( '_myStorage' ) ); // "{'a':1, 'b':2}" → {a:1, b:2}

Then, every N milliseconds produce the reverse process:
localStorage.setItem( '_myStorage', JSON.stringify( localObject ) );

With the onbeforeunload event, do the same.

The implementation of the idea is simple (the difficulty level of the task is low and is accessible even to a beginner). But, not everyone (including myself) thought of this before.
ObjectStorage Constructor Code
var ObjectStorage = function ObjectStorage( name, duration ) {
	var self,
		name = name || '_objectStorage',
		defaultDuration = 5000;
	// дабы не плодить кучу экземпляров, использующих один и тот же ключ хранилища, 
	// просто возвращаем единственный с заданным именем,
	// меняя только duration (если имеется)
	if ( ObjectStorage.instances[ name ] ) {
		self = ObjectStorage.instances[ name ];
		self.duration = duration || self.duration;
	} else {
		self = this;
		self._name = name;
		self.duration = duration || defaultDuration;
		self._init();
		ObjectStorage.instances[ name ] = self;
	}
	return self;
};
ObjectStorage.instances = {};
ObjectStorage.prototype = {
	// type == local || session
	_save: function ( type ) {
		var stringified = JSON.stringify( this[ type ] ),
			storage = window[ type + 'Storage' ];
		if ( storage.getItem( this._name ) !== stringified ) {
			storage.setItem( this._name, stringified );
		}
	},
	_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() {
			self.timeoutId = setTimeout( function () {
				self._save( 'local' );
				callee();
			}, self._duration );
		})();
		window.addEventListener( 'beforeunload', function () {
			self._save( 'local' );
			self._save( 'session' );
		});
	},
	// на случай, если нужно удалить таймаут (clearTimeout( storage.timeoutId ))
	timeoutId: null,
	local: {},
	session: {}
};



Using:
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};


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


Alternatively, when calling the ObjectStorage constructor, you can pass two arguments: name - the name of the key in the repository and duration - the interval for saving data in localStorage.
new ObjectStorage( '_myStorage', 1000 );

You can leave the name standard:
new ObjectStorage( null, 1000 );

Or you can change the duration after initialization:
var storage = new ObjectStorage;
storage.duration = 2000;

(you can also change storage._name, but this is not recommended, I even put a wand, such as a private property :))

Pros, compared to the solution by the link at the beginning of this article:
  • Performance: there are no getters, you do not need to pull the repository every time you call the key.
  • Compactness.
  • You can work as with a regular object:
    storage.local = {a:{}}
    storage.local.a.b = 5; // сработает
    a = storage.local.a;
    a.b = 5; // и так сработает
    
  • Built-in solution for sessionStorage.


Common cons:
  • If the browser does not close correctly (BSOD, power outage, etc.), you can lose (oh gods!) Work in the last M seconds (five by default). No matter how hard I tried to come up with a scenario where this moment is critical, I could not.


Of good.

Also popular now: