На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Правила раздела "Наши Исходники"
Раздел предназначен для публикации различных исходников и программных решений (в виде исходных текстов), которые Вы считаете достойными внимания и/или интересными. Язык исходника значения не имеет. Это может быть C/C++, Pascal, Perl, PHP, C#, Foth, Prolog или любой другой существующий язык программирования. Единственный момент – в названии темы этот язык должен быть указан. Например, «[C++] Представление чисел в римской записи». Сам исходный текст должен содержаться в первом посте темы. Если исходник занимает не больше одного-двух экранов, то допустимо его публикация непосредственно в посте. Иначе исходный текст должен быть прикреплен к посту в виде архива. Кроме того, первый пост должен содержать:

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

Плагиат крайне не приветствуется. Также не приветствуется публикация исходных текстов вирусов, крэков и т. п. информации. Это элементарно противозаконно.

Для быстрого поиска нужного исходника можно воспользоваться навигатором:
Быстрый поиск по разделу
Модераторы: Flex Ferrum
  
> [JS/ES6] Storage interface implementation
    Выкладывая в качестве примера, а заодно может быть кому понадобится.

    Сборка с помощью Babel ( https://babeljs.io/docs/setup/ ) с поддержкой ES6 ( http://babeljs.io/docs/plugins/preset-es2015/ ) и Flowtype ( http://babeljs.io/docs/plugins/transform-flow-strip-types/ и/или http://babeljs.io/docs/plugins/transform-flow-comments/ ):

    Repository.js
    ExpandedWrap disabled
      import AbstractAdapter from "/Storage/Adapters/AbstractAdapter";
      import MemoryAdapter from "/Storage/Adapters/MemoryAdapter";
       
      /**
       * Data repository
       */
      export default class Repository {
          /**
           * @param {String} prefix
           * @returns {Repository}
           */
          static create(prefix:String) {
              return new this(new MemoryAdapter(prefix));
          }
       
          /**
           * @type {AbstractAdapter}
           */
          adapter = null;
       
          /**
           * @param {AbstractAdapter} adapter
           */
          constructor(adapter:AbstractAdapter = null) {
              this.adapter = adapter || new MemoryAdapter();
          }
       
          /**
           * @param key
           * @returns {*}
           */
          get(key:String) {
              if (this.has(key)) {
                  return this.adapter.get(key).value;
              }
              return null;
          }
       
          /**
           * @param key
           * @param value
           * @param seconds
           * @returns {Repository}
           */
          set(key:String, value, seconds:Number = 0) {
              this.adapter.set(key, value || null, seconds * 1000);
              return this;
          }
       
          /**
           * @param key
           * @param seconds
           * @param callback
           * @returns {Repository}
           */
          remember(key:String, seconds:Number = 0, callback:Function) {
              if (!this.has(key)) {
                  this.set(key, seconds, callback());
              }
              return this;
          }
       
          /**
           * @param key
           * @returns {Number}
           */
          accessTime(key:String):Number {
              if (!this.has(key)) {
                  return -1;
              }
       
              var timeout = this.adapter.get(key).saveUp;
              if (timeout === 0) {
                  return 0;
              }
       
              return (this.adapter.get(key).saveUp - (new Date).getTime()) / 1000;
          }
       
          /**
           * @param key
           * @param callback
           * @returns {Repository}
           */
          rememberForever(key:String, callback:Function) {
              return this.remember(key, 0, callback);
          }
       
          /**
           * @param key
           * @returns {boolean}
           */
          has(key:String) {
              var value = this.adapter.get(key);
              if (value.value) {
                  if (value.saveUp === 0) {
                      return true;
                  } else if (value.saveUp >= (new Date).getTime()) {
                      return true;
                  } else {
                      this.remove(key);
                  }
              }
              return false;
          }
       
          /**
           * @returns {Repository}
           */
          clear() {
              for (var key in this.adapter.all()) {
                  this.adapter.remove(key);
              }
              return this;
          }
       
          /**
           * @param key
           * @returns {boolean}
           */
          remove(key:String) {
              return this.adapter.remove(key);
          }
       
          /**
           * @returns {{}}
           */
          all() {
              var result = {};
              for (var key in this.adapter.all()) {
                  if (this.has(key)) {
                      result[key] = this.get(key);
                  }
              }
              return result;
          }
       
          /**
           * @returns {Number}
           */
          get length() {
              return Object.keys(this.all()).length;
          }
       
          /**
           * @param object
           * @param mills
           * @returns {{saveUp: number, value}}
           */
          static createValue(object, mills:Number = 0) {
              return {
                  saveUp: mills <= 0 ? 0 : (new Date).getTime() + mills,
                  value:  JSON.parse(JSON.stringify(object))
              }
          }
       
          /**
           * @param object
           * @param mills
           * @returns {string}
           */
          static objectToValue(object, mills:Number = 0) {
              return JSON.stringify(this.createValue(object, mills));
          }
       
          /**
           * @param string
           * @returns {{saveUp: number, value: object}}
           */
          static valueToObject(string) {
              return JSON.parse(string);
          }
      }



    Adapters/AbstractAdapter.js

    ExpandedWrap disabled
      /**
       * Abstract adapter
       */
      export default class AbstractAdapter {
          /**
           * @type {string}
           */
          prefix = 'storage.';
       
          /**
           * @returns {string}
           */
          get escapedPrefix() {
              return this.prefix.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
          }
       
          /**
           * @param {string|null} prefix
           */
          constructor(prefix = null) {
              this.prefix = prefix || this.prefix;
          }
       
          /**
           * @param {String} key
           * @return {{saveUp: number, value: object}}
           */
          get(key:String) {
              throw new Error('Can not call abstract method directly')
          }
       
          /**
           * @param {String} key
           * @param value
           * @param {Number} mills
           * @return {boolean}
           */
          set(key:String, value, mills:Number = -1) {
              throw new Error('Can not call abstract method directly')
          }
       
          /**
           * @param key
           * @return {boolean}
           */
          remove(key:String) {
              throw new Error('Can not call abstract method directly')
          }
       
          /**
           * @param {String} key
           * @return {boolean}
           */
          has(key:String) {
              throw new Error('Can not call abstract method directly')
          }
       
          /**
           * @return {{}}
           */
          all() {
              throw new Error('Can not call abstract method directly')
          }
      }


    Adapters/MemoryAdapter.js

    ExpandedWrap disabled
      import Repository from "/Storage/Repository";
      import AbstractAdapter from "/Storage/Adapters/AbstractAdapter";
       
      export default class MemoryAdapter extends AbstractAdapter {
          /**
           * @type {Set}
           */
          keys = new Set;
       
          /**
           * @type {Map}
           */
          driver = new Map;
       
          /**
           * @param {String} key
           * @return {{saveUp: number, value: object}}
           */
          get(key:String) {
              if (this.has(key)) {
                  return Repository.valueToObject(
                      this.driver.get(key)
                  );
              }
       
              return Repository.createValue(null);
          }
       
          /**
           * @param {String} key
           * @param value
           * @param {Number} mills
           * @return {boolean}
           */
          set(key:String, value, mills:Number = 0) {
              if (!this.keys.has(key)) {
                  this.keys.add(key);
              }
       
              var json = Repository.objectToValue(value, mills);
              this.driver.set(key, json);
       
              return true;
          }
       
          /**
           * @param key
           * @return {boolean}
           */
          remove(key:String) {
              if (this.has(key)) {
                  this.keys.delete(key);
                  this.driver.delete(key);
                  return true;
              }
              return false;
          }
       
          /**
           * @param {String} key
           * @return {boolean}
           */
          has(key:String) {
              return this.keys.has(key) && this.driver.has(key);
          }
       
          /**
           * @returns {{}}
           */
          all() {
              var result = {};
       
              for (var key of this.keys.entries()) {
                  result[key] = this.get(key);
              }
       
              return result;
          }
      }


    Adapters/LocalStorageAdapter.js

    ExpandedWrap disabled
      import Repository from "/Storage/Repository";
      import AbstractAdapter from "/Storage/Adapters/AbstractAdapter";
       
      export default class LocalStorageAdapter extends AbstractAdapter {
          /**
           * @type {Storage}
           */
          driver = localStorage;
       
          /**
           * @param {String} key
           * @return {{saveUp: number, value: object}}
           */
          get(key:String) {
              if (this.has(key)) {
                  return Repository.valueToObject(
                      this.driver.getItem(this.prefix + key)
                  );
              }
       
              return Repository.createValue(null);
          }
       
          /**
           * @param {String} key
           * @param value
           * @param {Number} mills
           * @return {boolean}
           */
          set(key:String, value, mills:Number = 0) {
              var json = Repository.objectToValue(value, mills);
              this.driver.setItem(this.prefix + key, json);
       
              return true;
          }
       
          /**
           * @param key
           * @return {boolean}
           */
          remove(key:String) {
              if (this.has(key)) {
                  this.driver.removeItem(this.prefix + key);
                  return true;
              }
              return false;
          }
       
          /**
           * @param {String} key
           * @return {boolean}
           */
          has(key:String) {
              return !!this.driver.getItem(this.prefix + key);
          }
       
          /**
           * @returns {{}}
           */
          all() {
              var result = {};
       
              var regexp = new RegExp('^' + this.escapedPrefix + '(.*?)$');
              for (var key in this.driver) {
                  if (key.toString().match(regexp)) {
                      var matches = regexp.exec(key);
                      result[matches[1]] = this.get(matches[1]);
                  }
              }
       
              return result;
          }
      }


    Adapters/SessionStorageAdapter.js

    ExpandedWrap disabled
      import Repository from "/Storage/Repository";
      import AbstractAdapter from "/Storage/Adapters/AbstractAdapter";
       
      export default class SessionStorageAdapter extends AbstractAdapter {
          /**
           * @type {Storage}
           */
          driver = sessionStorage;
       
          /**
           * @param {String} key
           * @return {{saveUp: number, value: object}}
           */
          get(key:String) {
              if (this.has(key)) {
                  return Repository.valueToObject(
                      this.driver.getItem(this.prefix + key)
                  );
              }
       
              return Repository.createValue(null);
          }
       
          /**
           * @param {String} key
           * @param value
           * @param {Number} mills
           * @return {boolean}
           */
          set(key:String, value, mills:Number = 0) {
              var json = Repository.objectToValue(value, mills);
              this.driver.setItem(this.prefix + key, json);
       
              return true;
          }
       
          /**
           * @param key
           * @return {boolean}
           */
          remove(key:String) {
              if (this.has(key)) {
                  this.driver.removeItem(this.prefix + key);
                  return true;
              }
              return false;
          }
       
          /**
           * @param {String} key
           * @return {boolean}
           */
          has(key:String) {
              return !!this.driver.getItem(this.prefix + key);
          }
       
          /**
           * @returns {{}}
           */
          all() {
              var result = {};
       
              var regexp = new RegExp('^' + this.escapedPrefix + '(.*?)$');
              for (var key in this.driver) {
                  if (key.toString().match(regexp)) {
                      var matches = regexp.exec(key);
                      result[matches[1]] = this.get(matches[1]);
                  }
              }
       
              return result;
          }
      }


    Example:

    ExpandedWrap disabled
      import Repository from "/Storage/Repository";
      import LocalStorageAdapter from "/Storage/Adapters/LocalStorageAdapter";
       
      var repo = new Repository(new LocalStorageAdapter('test')); // LocalStorage адаптер с префиксом test
       
      var user = repo.remember('user', 60, () => { // Запомнить данные ExampleUser на 60 секунд в localStorage
          return new ExampleUser;
      });
    Сообщение отредактировано: Serafim -
    user posted image user posted image user posted image
    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
    0 пользователей:


    Рейтинг@Mail.ru
    [ Script Execution time: 0,0996 ]   [ 17 queries used ]   [ Generated: 21.09.19, 11:15 GMT ]