Метод length: количество записей

Метод length() в localForage возвращает количество сохранённых записей в текущем хранилище. Это асинхронная операция, основанная на Promise, и она предоставляет актуальное число ключей, доступных в выбранном драйвере (IndexedDB, WebSQL или localStorage как fallback).


Метод length() предназначен для получения размера хранилища в виде количества ключ-значение пар. В отличие от синхронных API браузерного localStorage, библиотека localForage всегда работает асинхронно, что позволяет не блокировать основной поток выполнения JavaScript.

Фактически length() отражает текущее состояние выбранного storage backend-а и учитывает все записи, сохранённые через localForage.


Сигнатура метода

localforage.length().then(function(numberOfKeys) {
  console.log(numberOfKeys);
});

Метод возвращает Promise<number>, где:

  • number — целое число, обозначающее количество элементов в хранилище
  • результат всегда актуален на момент выполнения запроса

Особенности асинхронного выполнения

Асинхронная природа length() обусловлена архитектурой IndexedDB, на котором чаще всего базируется localForage. Даже если драйвером выбран localStorage, библиотека сохраняет единый интерфейс и возвращает Promise.

Это означает:

  • нельзя получить значение напрямую
  • требуется использование .then() или async/await
  • операция не блокирует UI-поток

Пример с async/await:

async function getStorageSize() {
  const size = await localforage.length();
  console.log(size);
}

Поведение в разных драйверах

IndexedDB (основной драйвер)

При использовании IndexedDB метод length() выполняет запрос к объектному хранилищу и получает количество записей через встроенные механизмы индексации.

Особенности:

  • высокая производительность даже при больших объёмах данных
  • точный подсчёт без необходимости перебора ключей
  • корректная работа при тысячах записей

WebSQL (устаревший драйвер)

Если используется WebSQL (в старых браузерах), количество записей определяется через SQL-запрос вида COUNT(*).

Особенности:

  • чуть более медленная работа по сравнению с IndexedDB
  • зависимость от реализации браузера
  • поддержка ограничена устаревшими платформами

localStorage (fallback)

При использовании localStorage библиотека имитирует поведение асинхронного API.

Особенности:

  • фактический подсчёт через перебор ключей
  • потенциально медленнее при большом количестве записей
  • ограничение по объёму данных

Отличие от keys().length

Частая ошибка — попытка получить количество записей через:

localforage.keys().then(keys => keys.length);

Хотя результат будет аналогичным, есть принципиальная разница:

  • length() — оптимизированный метод, возвращающий число напрямую
  • keys() — возвращает массив всех ключей, что требует больше памяти

Таким образом:

  • length() предпочтителен для производительности
  • keys() используется, когда необходимы сами ключи

Производительность метода length

Метод оптимизирован под конкретный драйвер:

  • IndexedDB: O(1) операция через метаданные хранилища
  • WebSQL: O(log n) или O(1) в зависимости от индексации
  • localStorage: O(n), так как требуется перебор

При больших объёмах данных использование length() критично, так как он избегает полной загрузки всех ключей в память.


Использование в контроле состояния приложения

Метод часто применяется для:

  • определения наличия данных
  • проверки заполненности кэша
  • контроля прогресса загрузки
  • валидации состояния офлайн-данных

Пример проверки пустого хранилища:

localforage.length().then(count => {
  if (count === 0) {
    console.log("Хранилище пустое");
  } else {
    console.log("Есть сохранённые данные");
  }
});

Поведение при смене драйвера

Если в процессе работы приложения меняется драйвер:

localforage.setDriver([
  localforage.INDEXEDDB,
  localforage.WEBSQL,
  localforage.LOCALSTORAGE
]);

то length() всегда возвращает значение из текущего активного драйвера. Это важно учитывать, поскольку разные драйверы могут содержать разные наборы данных.


Ошибки и исключения

Метод может возвращать отклонённый Promise в случаях:

  • повреждение хранилища
  • отсутствие поддержки выбранного драйвера
  • ошибки доступа (например, приватный режим браузера)
  • проблемы инициализации IndexedDB

Пример обработки ошибок:

localforage.length()
  .then(count => {
    console.log(count);
  })
  .catch(err => {
    console.error("Ошибка получения длины:", err);
  });

Внутренняя логика работы

Внутри localForage метод length() делегируется драйверу:

  1. Определяется текущий storage backend

  2. Вызывается соответствующий метод драйвера:

    • IndexedDB: запрос к objectStore.count()
    • WebSQL: SELECT COUNT(*)
    • localStorage: перебор ключей с фильтрацией namespace
  3. Результат нормализуется

  4. Возвращается Promise с числом


Ограничения метода

Несмотря на простоту, метод имеет ряд особенностей:

  • не возвращает размер данных в байтах
  • не показывает распределение по ключам
  • не различает типы значений
  • зависит от текущего namespace instance

Сравнение с аналогами в других API

В отличие от:

  • localStorage.length (синхронный, глобальный)
  • IndexedDB.count() (низкоуровневый API)

метод length() в localForage:

  • унифицирован между драйверами
  • асинхронен
  • безопасен для UI-потока
  • изолирован по namespace

Типичные сценарии использования в архитектуре приложений

В SPA и PWA метод часто используется как часть:

  • системы кэширования данных
  • офлайн-first архитектуры
  • механизма синхронизации с сервером
  • проверки первичной инициализации приложения

Пример логики первичной загрузки:

async function initApp() {
  const hasData = await localforage.length();

  if (hasData === 0) {
    await fetchAndCacheData();
  } else {
    await loadFromCache();
  }
}

Влияние namespace на результат

Если используются разные инстансы localForage с разными конфигурациями storeName, то length() будет возвращать значение только для текущего пространства имён.

Это важно при архитектуре:

  • мультимодульных приложений
  • разделения кэша по сущностям
  • изоляции данных между feature-модулями

Поведение в условиях конкурентного доступа

При параллельных операциях записи и удаления:

  • результат length() может изменяться между вызовами
  • гарантия консистентности существует только на момент завершения Promise
  • нет транзакционной фиксации нескольких операций

Поэтому метод следует использовать как индикативный, а не как строго синхронизированное состояние.


Практические рекомендации по использованию

  • использовать length() вместо keys().length для больших хранилищ
  • не полагаться на результат как на строгую бизнес-метрику
  • комбинировать с iterate() при необходимости анализа данных
  • учитывать асинхронность в логике UI

Взаимодействие с другими методами localForage

Метод часто применяется совместно с:

  • setItem() — добавление данных
  • removeItem() — удаление данных
  • clear() — очистка хранилища
  • keys() — получение списка ключей

Пример контроля после очистки:

await localforage.clear();
const size = await localforage.length(); // всегда 0