Полная сигнатура iterate

Метод iterate в localForage имеет следующую сигнатуру:

iterate(iteratee, successCallback?)

Полная поведенческая модель метода строится вокруг последовательного перебора всех ключей хранилища с доступом к значениям, при этом API остаётся асинхронным и унифицированным для разных драйверов (IndexedDB, WebSQL, localStorage).

Основной параметр: iteratee

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

Внутри функции this также ссылается на текущее значение value, что важно при использовании обычных функций вместо стрелочных.

Второй параметр (необязательный): successCallback

(err, result) => void
  • err — ошибка, если она произошла во время обхода
  • result — итоговое значение, возвращаемое последней итерацией

Метод также возвращает Promise, что делает возможным использование async/await.

Поведение метода

iterate последовательно проходит по всем элементам хранилища. В отличие от методов работы с ключами (keys, length), он сразу предоставляет доступ к значениям без дополнительных обращений к getItem.

Ключевая особенность заключается в том, что обход происходит в порядке, определяемом внутренним драйвером хранилища. Это означает, что:

  • порядок не гарантируется как строго вставочный
  • IndexedDB может возвращать данные в порядке ключей индекса
  • localStorage-драйвер может возвращать значения в порядке перечисления ключей

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

Метод возвращает Promise, который резолвится в значение, возвращённое последним вызовом iteratee.

Если в теле iteratee происходит возврат значения, оно не влияет на поток обхода, но сохраняется как потенциальный результат всей операции.

Пример поведения:

const result = await localforage.iterate((value, key, index) => {
  return value;
});

result будет равен значению последнего элемента, а не промежуточным результатам.

Принцип работы итератора

Каждый вызов iteratee выполняется синхронно относительно самой итерации, но вся операция остаётся асинхронной.

Последовательность:

  1. Получение списка ключей из драйвера
  2. Последовательное извлечение значений
  3. Вызов iteratee для каждого элемента
  4. Сбор результата последнего возврата
  5. Завершение Promise

Важно, что нельзя прервать цикл стандартным break — возврат из функции не влияет на продолжение итерации.

Особенности контекста this

При использовании классической функции:

localforage.iterate(function(value, key, index) {
  console.log(this === value);
});

this указывает на текущее значение. Это поведение сохраняется для обратной совместимости, но в современных кодовых базах чаще используется явное обращение к value.

Стрелочные функции не имеют собственного this, поэтому:

localforage.iterate((value) => {
  console.log(this); // не связано с value
});

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

Подсчёт суммы значений

let sum = 0;

await localforage.iterate((value) => {
  if (typeof value === 'number') {
    sum += value;
  }
});

console.log(sum);

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

let found;

await localforage.iterate((value, key) => {
  if (value && value.active === true) {
    found = { key, value };
  }
});

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

Формирование структуры данных

const map = {};

await localforage.iterate((value, key) => {
  map[key] = value;
});

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

iterate выполняет последовательный обход, что означает:

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

Оптимизация достигается за счёт минимизации логики внутри iteratee и избегания тяжёлых вычислений на каждой итерации.

Ошибки и обработка исключений

Если во время итерации происходит ошибка чтения из хранилища, Promise отклоняется, а successCallback не вызывается.

localforage.iterate((value) => {
  if (!value) {
    throw new Error('Invalid value');
  }
});

Такое исключение прерывает выполнение всей операции.

Сравнение с другими методами обхода

В отличие от keys() и последующего getItem():

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

По сравнению с ручным циклом через keys:

const keys = await localforage.keys();
for (const key of keys) {
  const value = await localforage.getItem(key);
}

iterate объединяет эти операции в один механизм, снижая накладные расходы и упрощая структуру кода.

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

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

Типичное поведение в разных драйверах

IndexedDB

  • наиболее стабильный и предсказуемый вариант
  • высокая производительность
  • асинхронный доступ к записям

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

  • возможны задержки при больших таблицах
  • ограниченная поддержка

localStorage

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