Библиотека idb-keyval предоставляет простой
интерфейс для работы с IndexedDB через промисы, что позволяет эффективно
хранить и извлекать данные в браузере. Когда требуется выполнить
несколько операций одновременно — например, чтение или запись нескольких
ключей — возникает необходимость параллельного выполнения
операций, и здесь ключевую роль играет
Promise.all.
Promise.all принимает массив промисов и возвращает новый
промис, который выполняется, когда все промисы завершены
успешно, или отклоняется, если хотя бы один промис завершился с
ошибкой.
Пример базового применения:
import { set, get } from 'idb-keyval';
const operations = [
set('user1', { name: 'Alice', age: 25 }),
set('user2', { name: 'Bob', age: 30 }),
set('user3', { name: 'Charlie', age: 28 })
];
Promise.all(operations)
.then(() => console.log('Все данные сохранены'))
.catch(err => console.error('Ошибка при сохранении:', err));
Здесь три операции записи выполняются параллельно. Важно отметить, что параллельное выполнение ускоряет обработку, так как не требуется дожидаться завершения одной операции перед началом другой.
Для чтения нескольких значений из хранилища idb-keyval
параллельно удобно использовать тот же подход с
Promise.all.
import { get } from 'idb-keyval';
const keys = ['user1', 'user2', 'user3'];
const readOperations = keys.map(key => get(key));
Promise.all(readOperations)
.then(results => {
results.forEach((data, index) => {
console.log(`${keys[index]}:`, data);
});
})
.catch(err => console.error('Ошибка при чтении данных:', err));
Использование map позволяет динамически формировать
массив промисов для любых ключей. Результаты возвращаются в том же
порядке, что и массив промисов, что облегчает сопоставление данных с
ключами.
Иногда требуется выполнить последовательность операций для каждого элемента, например: прочитать значение, модифицировать его и записать обратно. Параллельное выполнение может быть реализовано следующим образом:
import { get, set } from 'idb-keyval';
const keys = ['user1', 'user2', 'user3'];
const updateOperations = keys.map(async key => {
const user = await get(key);
if (user) {
user.lastLogin = new Date().toISOString();
return set(key, user);
}
});
Promise.all(updateOperations)
.then(() => console.log('Данные обновлены'))
.catch(err => console.error('Ошибка при обновлении:', err));
Ключевой момент здесь — использование асинхронной функции
внутри map, которая возвращает промис. Благодаря
Promise.all все обновления выполняются одновременно, что
сокращает общее время операции.
При параллельных операциях критически важно учитывать возможность
ошибок. Если хотя бы один промис завершится с ошибкой,
Promise.all отклонится, и выполнение остальных операций не
будет остановлено, но результат вернётся как ошибка.
Для более гибкой обработки ошибок можно использовать
Promise.allSettled:
const operations = keys.map(async key => {
try {
const value = await get(key);
return { key, value };
} catch (err) {
return { key, error: err };
}
});
Promise.allSettled(operations)
.then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log(`${result.value.key}:`, result.value.value);
} else {
console.error(`Ошибка ключа ${result.reason.key}:`, result.reason.error);
}
});
});
Promise.allSettled возвращает результаты всех
промисов независимо от ошибок, что удобно для ситуаций, когда
важно завершить обработку каждого элемента.
Использование Promise.all в сочетании с
idb-keyval делает работу с IndexedDB прозрачной,
асинхронной и эффективной, особенно при необходимости
параллельной обработки множества операций.