Web Storage API предоставляет разработчикам механизм для сохранения данных ключ-значение, связанных с источником текущей страницы. Это значительное улучшение по сравнению с использованием файлов cookie на стороне клиента для сохранения битов данных, обычно позволяющих хранить до 5 МБ данных. API простой:

localStorage.setItem('color', 'blue')
localStorage.getItem('color') // 'blue'
localStorage.removeItem('color')

Несколько примеров того, где вы можете использовать localStorage:

  • Хранить настройки пользовательского интерфейса (фильтры, состояние пользовательского интерфейса), которые не обязательно сохранять на сервере.
  • Хранилище данных для автономных приложений, которым не нужен сервер
  • Совместное использование состояния между различными IFrame на одной странице
  • Кэшируйте данные для автономного использования или повышения производительности

В некоторых случаях вы можете не захотеть создавать API или уровень сохраняемости на сервере, но все же хотите сохранить содержимое localStorage в облаке. Представьте себе веб-приложение с пользовательским интерфейсом поиска, который позволяет пользователю выбирать некоторые фильтры. С точки зрения UX вы можете захотеть сохранить состояние настроек фильтра, которое выбрал пользователь, чтобы ему не нужно было каждый раз выбирать их заново. Это вполне может храниться только в localStorage и не усложнять логику на стороне сервера. Но что, если пользователь откроет веб-приложение с другого устройства? Пользовательский опыт был бы лучше, если бы там также были доступны настройки фильтра.

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

Однако одним недостатком API веб-хранилища является то, что он предлагает только синхронный API. Использование службы удаленного хранилища требует асинхронного сетевого обмена, что затрудняет разработку полностью совместимого API из-за ограничений на синхронный сетевой ввод-вывод, особенно в браузерах. По этой причине вместо того, чтобы ломать синхронную эмуляцию API, давайте реализуем асинхронный API, который поддерживает async и поддерживает Promises.

Давайте воспользуемся нашим собственным модулем kvdb.io-commonjs для его сборки!

class KVdbWebStorage {
  constructor(bucket) {
    this.bucket = bucket
  }
  // When passed a number n, this method will return the name of the nth key in the storage.
  async key(index) {
    return this.bucket.list({skip: index, limit: 1})
      .then(keyName => keyName)
      .catch(err => null)
  }
  // When passed a key name, will return that key's value.
  async getItem(keyName) {
    return this.bucket.get(keyName)
      .then(keyValue => keyValue)
      .catch(err => null)
  }
  // When passed a key name and value, will add that key to the storage, or update that key's value if it already exists.
  async setItem(keyName, keyValue) {
    return this.bucket.set(keyName, keyValue)
  }
  // When passed a key name, will remove that key from the storage.
  async removeItem(keyName) {
    return this.bucket.delete(keyName)
  }
  // Returns an integer representing the number of data items stored in the Storage object.
  async length() {
    return this.bucket.list()
      .then(keys => keys.length)
      .catch(err => -1)
  }
  // When invoked, will empty all keys out of the storage.
  async clear() {
    const keys = await this.bucket.list()
    const waiting = keys.map(key => this.bucket.delete(key))
    return Promise.all(waiting)
  }
}

Использовать его так же просто, как и localStorage, просто создайте экземпляр с помощью корзины KVdb и ключа API:

const bucket = KVdb.bucket('MY_BUCKET', 'MY_SECRET')
const kvdbStorage = new KVdbWebStorage(bucket)
kvdbStorage.setItem('foo', 'bar')
  .then(() => kvdbStorage.getItem('foo'))
  .then(() => console.log('get: ', value))
  .catch(err => console.error('error: ', err))

Хотя можно рассматривать localStorage как объект и напрямую устанавливать для него ключи, вместо этого рекомендуется использовать методы установки и получения, чтобы обеспечить асинхронные серверные части хранилища, такие как тот, который мы создали выше.

Фактически, популярная библиотека localForage основана на этом подходе и предоставляет интерфейс, похожий на localStorage, с поддержкой различных драйверов или бэкендов хранилища, таких как localStorage, IndexedDB и пользовательских. Последняя версия модуля kvdb.io-commonjs имеет встроенную поддержку localForage, что упрощает использование KVdb в качестве бэкенда:

Подводя итог, мы увидели, как реализовать оболочку API веб-хранилища, поддерживаемую KVdb, и насколько она минимальна для поддержания совместимости API с localStorage. А если вы уже используете localStorage и хотите сохранить его в облаке независимо от поставщика, ознакомьтесь с localForage и его API.

Первоначально опубликовано на https://blog.kvdb.io.