Dexie.js построен поверх IndexedDB и полностью наследует её модель ошибок, при этом добавляя собственный слой нормализации и типизации исключений. В реальных приложениях работа с IndexedDB неизбежно сопровождается различными сбоями: конфликтами транзакций, ошибками квот, нарушениями схемы, отменами операций и асинхронными сбоями. Поэтому централизованная обработка ошибок становится ключевым элементом архитектуры хранилища данных.
Dexie предоставляет механизм глобального перехвата ошибок, который позволяет единообразно обрабатывать исключения на уровне всей базы данных, не дублируя обработчики в каждом запросе.
Ошибки в Dexie можно условно разделить на несколько категорий:
Dexie оборачивает большинство ошибок в собственный объект
DexieError, сохраняя исходную причину в поле
inner.
Ключевой момент: любая операция Dexie возвращает Promise, а значит, ошибка всегда проходит через promise-цепочку и может быть перехвачена централизованно.
Основной механизм глобальной обработки ошибок — событие уровня библиотеки:
Dexie.on("error", (error) => {
console.error("Глобальная ошибка Dexie:", error);
});
Этот обработчик вызывается при любой необработанной ошибке, которая
не была перехвачена локально в .catch() или внутри
транзакции.
Важно понимать: это не аналог window.onerror. Dexie
работает на уровне своих промисов и транзакций.
Отдельный тип глобального события связан с конфликтами версий базы:
Dexie.on("blocked", () => {
console.warn("База данных заблокирована другой вкладкой");
});
Хотя это не ошибка в классическом смысле, поведение приложения при блокировке часто обрабатывается вместе с глобальными ошибками.
При обновлении схемы базы возможны сбои миграции. Dexie позволяет отслеживать изменения версии:
Dexie.on("versionchange", (event) => {
console.warn("Версия базы данных изменилась извне");
});
Ошибки миграции чаще всего связаны с:
Хотя событие не является обработчиком ошибок напрямую, оно тесно связано с глобальной стратегией устойчивости базы.
Помимо глобального уровня библиотеки существует уровень конкретной базы данных:
const db = new Dexie("MyDatabase");
db.on("error", (error) => {
console.error("Ошибка базы данных:", error);
});
Этот обработчик более специфичен и применяется только к одной базе. В сложных приложениях это предпочтительнее глобального Dexie.on(“error”), так как позволяет разделять контексты.
Dexie использует транзакционную модель IndexedDB. Ошибка внутри транзакции приводит к её автоматическому откату.
db.transaction("rw", db.users, async () => {
await db.users.add({ id: 1, name: "Alex" });
await db.users.add({ id: 1, name: "Duplicate" });
});
В этом случае возникает ошибка уникальности ключа, и вся транзакция откатывается.
Если ошибка не перехвачена внутри .catch(), она попадёт
в глобальный обработчик.
Dexie следует строгому правилу приоритета:
.catch() на запросе;transaction().catch();db.on("error");Dexie.on("error").Если ошибка обработана на более низком уровне, она не всплывает вверх.
Dexie нормализует ошибки в единый формат:
name — тип ошибки;message — описание;inner — исходная ошибка IndexedDB;stack — стек вызовов;Пример обработки:
db.on("error", (error) => {
if (error.name === "QuotaExceededError") {
console.warn("Превышена квота хранения");
}
});
Одна из наиболее частых ошибок в браузерных приложениях — превышение лимита хранилища.
Dexie не может автоматически освободить место, поэтому глобальный обработчик часто используется для:
Dexie.on("error", (error) => {
if (error.name === "QuotaExceededError") {
console.error("Хранилище переполнено");
}
});
AbortError возникает при отмене транзакции или запроса:
db.on("error", (error) => {
if (error.name === "AbortError") {
// операция отменена системой или пользователем
}
});
В Dexie AbortError часто появляется при:
При несовместимости версий базы возникает ошибка инициализации:
Dexie.on("error", (error) => {
if (error.name === "VersionError") {
console.error("Ошибка версии базы данных");
}
});
Это критическая ошибка, так как она блокирует доступ к данным до корректного обновления схемы.
Dexie транслирует IndexedDB ConstraintError при нарушении индексов:
db.on("error", (error) => {
if (error.name === "ConstraintError") {
console.warn("Нарушение ограничения индекса");
}
});
Dexie полностью поддерживает async/await, но ошибки внутри асинхронных функций могут не обрабатываться локально:
db.on("error", (error) => {
console.error("Необработанная ошибка:", error);
});
async function run() {
await db.users.add({ id: 1 });
await db.users.add({ id: 1 });
}
Если run() не окружена try/catch, ошибка
попадёт в глобальный обработчик.
Глобальный обработчик часто используется не только для логирования, но и для восстановления состояния приложения:
Dexie не навязывает стратегию восстановления, но предоставляет полный доступ к контексту ошибки.
Поведение глобальных ошибок может отличаться:
Dexie выравнивает различия, но глобальный обработчик остаётся ключевой точкой унификации поведения.
Глобальная обработка ошибок в Dexie.js выполняет роль последнего уровня защиты:
При этом он не заменяет локальную обработку, а дополняет её, формируя многоуровневую систему устойчивости работы с IndexedDB.