Хук creating в Dexie.js перехватывает момент добавления
новой записи в таблицу до фактической записи данных в IndexedDB. Он
выполняется синхронно или асинхронно (в зависимости от реализации
обработчика) и позволяет модифицировать объект, запретить вставку или
дополнить данные служебными полями. Это один из ключевых механизмов
управления целостностью данных на уровне ORM-слоя.
Хук creating регистрируется на уровне таблицы:
db.users.hook('creating', function (primKey, obj, trans) {
// логика
});
Параметры обработчика:
Возвращаемое значение хука может влиять на первичный ключ или модификацию объекта в зависимости от логики обработки.
creating вызывается строго до записи в IndexedDB, но
после начала транзакции. Последовательность выглядит следующим
образом:
creatingЭто делает хук подходящим для:
Одной из ключевых особенностей является возможность мутировать объект напрямую:
db.users.hook('creating', function (primKey, obj, trans) {
obj.createdAt = Date.now();
obj.isActive = true;
});
В этом случае изменения будут сохранены вместе с записью без дополнительного кода в бизнес-логике.
Важно учитывать, что объект передаётся по ссылке, и любые изменения становятся частью сохраняемой структуры.
Хук позволяет влиять на значение первичного ключа, возвращая новое значение:
db.orders.hook('creating', function (primKey, obj, trans) {
if (!primKey) {
return crypto.randomUUID();
}
});
Если возвращается значение:
Это полезно при кастомной генерации идентификаторов вне IndexedDB auto-increment.
Dexie поддерживает асинхронные хуки через возвращение
Promise. Это позволяет выполнять внешние операции перед
сохранением:
db.users.hook('creating', async function (primKey, obj, trans) {
const profile = await fetch(`/api/profile/${obj.id}`).then(r => r.json());
obj.profileSnapshot = profile;
});
Особенности:
Третий аргумент trans даёт доступ к текущей транзакции
Dexie:
db.logs.hook('creating', function (primKey, obj, trans) {
trans.on('complete', () => {
console.log('Запись завершена');
});
});
Через транзакцию можно:
complete, error,
abortcreating часто используется как слой валидации:
db.users.hook('creating', function (primKey, obj) {
if (!obj.email) {
throw new Error('Email обязателен');
}
if (obj.age < 0) {
throw new Error('Некорректный возраст');
}
});
При выбрасывании исключения:
Хук удобен для приведения данных к единому формату:
db.messages.hook('creating', function (primKey, obj) {
obj.text = obj.text.trim();
obj.createdAt = obj.createdAt || Date.now();
obj.tags = Array.isArray(obj.tags) ? obj.tags : [];
});
Это снижает необходимость предварительной обработки на уровне UI или сервисного слоя.
Несмотря на гибкость, хук имеет ограничения:
Если зарегистрировано несколько хуков creating, они
выполняются последовательно в порядке добавления.
Хуки действуют строго на уровне конкретной таблицы:
db.users.hook('creating', fn);
db.orders.hook('creating', fn);
Логика не пересекается между таблицами, даже если структуры объектов похожи.
Типичный сценарий — добавление audit-полей:
db.audit.hook('creating', function (primKey, obj) {
obj.createdAt = new Date().toISOString();
obj.createdBy = 'system';
});
При необходимости можно использовать данные транзакции или внешнего контекста приложения для заполнения этих полей.
creating часто используется вместе с:
updating — для модификации при обновленииdeleting — для контроля удаленияreading — для трансформации данных при чтенииСовместное использование позволяет строить единый слой бизнес-логики внутри Dexie без необходимости дублирования кода в разных частях приложения.