Метод iterate: обход всех записей

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

Метод iterate в библиотеке localForage предназначен для последовательного обхода всех сохранённых записей в текущем хранилище.

localforage.iterate(iteratorCallback)

или с использованием Promise:

localforage.iterate(iteratorCallback).then(finalValue => {
  // результат завершения итерации
});

Метод всегда возвращает Promise, который резолвится после завершения обхода всех элементов.


Назначение и общая модель работы

iterate предоставляет универсальный способ пройти по всем ключ-значение парам независимо от используемого драйвера хранения (IndexedDB, WebSQL или localStorage).

Ключевая особенность заключается в том, что метод абстрагирует различия между механизмами хранения и предоставляет единый интерфейс итерации.


Сигнатура callback-функции

Функция-итератор имеет следующую форму:

function iteratorCallback(value, key, iterationNumber) {
    // логика обработки
}

Параметры:

  • value — сохранённое значение
  • key — ключ записи
  • iterationNumber — порядковый номер текущей итерации (начиная с 1)

Возвращаемое значение callback не влияет на процесс обхода.


Особенности выполнения

Асинхронная природа

Итерация выполняется асинхронно. Даже если хранилище небольшое, выполнение не блокирует основной поток.

Отсутствие гарантированного порядка

Порядок обхода записей не гарантируется. Он зависит от:

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

Следовательно, логика не должна опираться на последовательность ключей.


Возвращаемое значение

Метод возвращает Promise, который резолвится после завершения обхода:

localforage.iterate((value, key, index) => {
    console.log(key, value, index);
}).then(() => {
    console.log('итерация завершена');
});

Значение, передаваемое в then, обычно не используется, так как результат формируется в процессе callback-обработки.


Примеры использования

Базовый обход всех элементов

localforage.iterate((value, key, index) => {
    console.log(`№${index}: ${key} =`, value);
});

Подсчёт количества элементов с определённым условием

let count = 0;

localforage.iterate((value) => {
    if (value && value.active) {
        count++;
    }
}).then(() => {
    console.log('Активных записей:', count);
});

Поиск элемента по условию

let foundKey = null;

localforage.iterate((value, key) => {
    if (value.type === 'target') {
        foundKey = key;
    }
}).then(() => {
    console.log('Найденный ключ:', foundKey);
});

Ограничения при поиске и попытках прерывания

Метод не предоставляет встроенной возможности остановить итерацию досрочно. Даже если внутри callback выполняется условие нахождения нужного значения, обход продолжается до конца.

localforage.iterate((value) => {
    if (value === 'stop-condition') {
        // нельзя прервать итерацию стандартным способом
    }
});

Это связано с тем, что API построен на асинхронных курсорах и унифицирован для разных драйверов.


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

IndexedDB

  • Используется курсорная модель
  • Высокая производительность при больших объёмах данных
  • Нестабильный порядок без сортировки

WebSQL

  • Итерация через SQL-запросы
  • Возможен более предсказуемый порядок, но зависит от запроса

localStorage

  • Эмуляция итерации через перебор ключей
  • Наименее производительный вариант

Параметры выполнения и контекст

Метод работает в контексте текущего экземпляра localForage:

const store = localforage.createInstance({
    name: 'app'
});

store.iterate((value, key) => {
    console.log(key, value);
});

Каждый экземпляр имеет собственное пространство ключей и независимую итерацию.


Использование для агрегации данных

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

Суммирование значений

let sum = 0;

localforage.iterate((value) => {
    if (typeof value === 'number') {
        sum += value;
    }
}).then(() => {
    console.log('Сумма:', sum);
});

Построение массива из хранилища

const items = [];

localforage.iterate((value, key) => {
    items.push({ key, value });
}).then(() => {
    console.log(items);
});

Типичные сценарии применения

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

Особенности производительности

При больших объёмах данных производительность зависит от:

  • количества записей
  • типа драйвера
  • сложности callback-функции

IndexedDB показывает наилучшие результаты, так как использует ленивую загрузку через курсоры. localStorage значительно уступает из-за синхронной природы и строкового хранения.


Побочные эффекты и осторожности

Callback вызывается для каждой записи, поэтому:

  • нельзя выполнять тяжёлые синхронные операции без необходимости
  • нежелательно изменять структуру хранилища внутри итерации
  • следует избегать вложенных setItem/removeItem без строгой логики

Изменение данных во время итерации может приводить к непредсказуемым результатам, особенно в IndexedDB.


Итоговая модель поведения метода

  • проходит по всем ключам текущего хранилища
  • вызывает callback для каждого элемента
  • не гарантирует порядок
  • не поддерживает прерывание
  • завершает выполнение Promise после полного обхода