Reusable IDB transaction configuration + update

- Use standard DOMException when rejecting
This commit is contained in:
awsr
2026-01-27 13:41:53 -08:00
parent ef416f9628
commit 2cb68b7432
+33 -18
View File
@@ -36,6 +36,37 @@ async function initIndexDB() {
if (!db) await createDB();
}
/**
* Reusable setup for handling IDB transactions.
* @param {Object} resources - Required resources for implementation
* @param {IDBTransaction} resources.transaction
* @param {AbortSignal} resources.signal
* @param {Function} resources.resolve
* @param {Function} resources.reject
* @param {*} resolveValue - Value to resolve the outer Promise with
* @returns {() => void} - Function for manually aborting the transaction
*/
function configureTransactionAbort({ transaction, signal, resolve, reject }, resolveValue) {
function abortTransaction() {
signal.removeEventListener('abort', abortTransaction);
transaction.abort();
}
signal.addEventListener('abort', abortTransaction);
transaction.onabort = () => {
signal.removeEventListener('abort', abortTransaction);
reject(new DOMException(`Aborting database transaction. ${signal.reason}`, 'AbortError'));
};
transaction.onerror = (e) => {
signal.removeEventListener('abort', abortTransaction);
reject(new Error('Database transaction error.', e));
};
transaction.oncomplete = () => {
signal.removeEventListener('abort', abortTransaction);
resolve(resolveValue);
};
return abortTransaction;
}
async function add(record) {
if (!db) return null;
return new Promise((resolve, reject) => {
@@ -161,24 +192,8 @@ async function idbFolderCleanup(keepSet, folder, signal) {
}
return new Promise((resolve, reject) => {
const transaction = db.transaction('thumbs', 'readwrite');
function abortTransaction() {
signal.removeEventListener('abort', abortTransaction);
transaction.abort();
}
signal.addEventListener('abort', abortTransaction);
transaction.onabort = () => {
signal.removeEventListener('abort', abortTransaction);
reject(`Aborting. ${signal.reason}`); // eslint-disable-line prefer-promise-reject-errors
};
transaction.onerror = () => {
signal.removeEventListener('abort', abortTransaction);
reject(new Error('Database transaction error'));
};
transaction.oncomplete = async () => {
signal.removeEventListener('abort', abortTransaction);
resolve(totalRemovals);
};
const props = { transaction, signal, resolve, reject };
const abortTransaction = configureTransactionAbort(props, totalRemovals);
try {
const store = transaction.objectStore('thumbs');
removals.forEach((entry) => { store.delete(entry); });