Этим постом я бы хотел исправиться и предложить адекватный способ работы с хранилищем, как с объектом. Код из поста «Работа с локальным хранилищем, как с объектом? Легко!» использовать крайне не рекомендую, там всё плохо (минусы изложены внизу). Цель данного — объяснить всем тем, кто добавил статью по ссылке в избранное или поставил плюсик, никогда не использовать этот код.
Сейчас же я хочу продемонстрировать простейшую идею, предложенную Scalar в комментарии.
При загрузке страницы (даже до события готовности DOM дерева) обращаемся к хранилищу (в данном случае, это localStorage и sessionStorage), получить JSON, десериализовать его и положить в какую-нибудь переменную.
Затем, каждые N миллисекунд производить обратный процесс:
При событии onbeforeunload делать то же самое.
Реализация идеи проста (уровень сложности задачи низок и доступен даже новичку). Но, не все (и я в том числе) до этого додумались.
Использование:
Перезагружаете страницу,
Как вариант, при вызове конструктора ObjectStorage, можно передать два аргумента: name — имя ключа в хранилище и duration — интервал сохранения данных в localStorage.
Можно оставить имя стандартным:
А можно и после инициализации изменить duration:
(можно и storage._name изменить, но это не рекомендуется, я даже палочку поставил, типа приватное свойство :))
Плюсы, по сравнению с решением по ссылке в начале этой статьи:
Общие минусы:
Добра.
Сейчас же я хочу продемонстрировать простейшую идею, предложенную 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 ) { 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: {} };
Использование:
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 секунд (по умолчанию, пять). Сколько я ни старался придумать сценария, где этот момент критичен, не смог.
Добра.
