Метод iterate в localForage представляет собой механизм
последовательного обхода всех ключей и значений хранилища с доступом к
каждому элементу по очереди. Базовая сигнатура выглядит следующим
образом:
localforage.iterate((value, key, iterationNumber) => {
// обработка элемента
});
Колбэк получает три аргумента:
В отличие от методов getItem или keys,
iterate ориентирован не на возврат результата, а на
потоковую обработку всех элементов хранилища.
iterate не возвращает результат напрямуюКлючевая особенность модели выполнения заключается в том, что
iterate не формирует возвращаемое значение на уровне
метода. Следующий код не создаёт накопленный результат:
const result = localforage.iterate((value) => {
return value;
});
Переменная result не содержит массив или агрегированную
структуру данных, поскольку возвращаемое значение колбэка
игнорируется.
Причина такого поведения — потоковая природа обработки. Хранилище может содержать большое количество записей, и создание промежуточной структуры по умолчанию не навязывается API.
Основной способ получения результата из iterate
заключается в ручном накоплении данных:
const result = [];
await localforage.iterate((value, key) => {
result.push({ key, value });
});
console.log(result);
Здесь формируется массив объектов, где каждый элемент содержит ключ и значение. Такая структура используется для последующей обработки, фильтрации или сериализации.
Вариант с трансформацией значений:
const values = [];
await localforage.iterate((value) => {
values.push(value);
});
Результат формируется строго в порядке итерации, который определяется внутренним драйвером хранилища (IndexedDB, WebSQL или localStorage).
iterate часто используется для выборочной агрегации
данных без предварительного получения полного набора ключей:
const filtered = [];
await localforage.iterate((value, key) => {
if (key.startsWith('cache_')) {
filtered.push(value);
}
});
Фильтрация выполняется на лету, что позволяет избегать лишних операций чтения и дополнительной памяти.
Дополнительный вариант с условной логикой:
const activeItems = [];
await localforage.iterate((value) => {
if (value && value.active) {
activeItems.push(value);
}
});
MapДля случаев, где важен быстрый доступ по ключу, результат
iterate часто преобразуется в Map:
const map = new Map();
await localforage.iterate((value, key) => {
map.set(key, value);
});
Такой подход позволяет:
При необходимости сохранения порядка итерации вместе с ключами формируется индексированный массив:
const indexed = [];
await localforage.iterate((value, key, index) => {
indexed[index - 1] = { key, value };
});
Использование iterationNumber позволяет точно
контролировать позицию элемента в итоговой структуре.
Несмотря на то что iterate поддерживает
async/await внутри колбэка, возврат промисов не влияет на
сам процесс обхода:
await localforage.iterate(async (value, key) => {
const processed = await someAsyncTransform(value);
console.log(key, processed);
});
Однако порядок выполнения асинхронных операций внутри колбэка не гарантирует параллельности; итерация остаётся последовательной.
Важно учитывать, что накопление результатов через асинхронные операции может приводить к увеличению времени полного прохода.
Прямого механизма досрочного выхода из iterate не
предусмотрено. Конструкция:
await localforage.iterate((value, key) => {
if (key === 'target') {
return;
}
});
не останавливает цикл, а лишь завершает текущий вызов колбэка.
Попытки имитации прерывания обычно сводятся к генерации ошибки:
try {
await localforage.iterate((value, key) => {
if (key === 'stop') {
throw new Error('break');
}
});
} catch (e) {
// обработка завершения
}
Такой подход используется как обходной механизм, но рассматривается как побочный эффект, а не штатная функциональность API.
Наиболее универсальный паттерн построения результата заключается в вынесении состояния за пределы колбэка:
function collectAll() {
const state = {
entries: [],
count: 0
};
return localforage.iterate((value, key) => {
state.entries.push([key, value]);
state.count++;
}).then(() => state);
}
Подобная конструкция позволяет:
iterate для построения выборокТипичный сценарий получения результата — построение выборки с несколькими условиями:
const selection = [];
await localforage.iterate((value, key) => {
if (key.startsWith('user_') && value?.enabled) {
selection.push(value);
}
});
Подобная модель заменяет комбинацию keys() +
getItem() и уменьшает количество обращений к хранилищу.
iterate часто используется для вычисления сводных
значений:
let sum = 0;
await localforage.iterate((value) => {
if (typeof value === 'number') {
sum += value;
}
});
Другой вариант — группировка по категориям:
const groups = {};
await localforage.iterate((value) => {
const type = value.type || 'unknown';
if (!groups[type]) {
groups[type] = [];
}
groups[type].push(value);
});
Если в хранилище отсутствуют данные, iterate завершается
мгновенно, не вызывая колбэк ни одного раза. При этом возвращаемое
значение остаётся undefined, если не используется внешняя
обёртка.
await localforage.iterate(() => {
// не выполнится
});
Порядок итерации зависит от используемого драйвера:
Следовательно, построение результата через массив или индексированную структуру не должно полагаться на стабильную сортировку без дополнительной логики.
iterate с другими APIРезультаты iterate часто используются совместно с
другими методами:
const keys = [];
await localforage.iterate((_, key) => {
keys.push(key);
});
const values = await Promise.all(
keys.map(k => localforage.getItem(k))
);
Хотя такой подход дублирует данные, он может применяться для разделения этапов фильтрации и последующей асинхронной обработки.
Наиболее распространённая ошибка — попытка трактовать
iterate как функцию, возвращающую массив:
const data = await localforage.iterate(() => {});
// data не содержит список элементов
Другой частый случай — ожидание синхронного поведения:
const result = [];
localforage.iterate((v) => {
result.push(v);
});
console.log(result); // может быть пустым
Корректная модель всегда опирается на завершение промиса.