Skip to content

Instantly share code, notes, and snippets.

@JamesTheAwesomeDude
Last active April 11, 2024 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamesTheAwesomeDude/87dacf390eadf469e7200928c115e182 to your computer and use it in GitHub Desktop.
Save JamesTheAwesomeDude/87dacf390eadf469e7200928c115e182 to your computer and use it in GitHub Desktop.
async indexedDB wrapper
async function idb_open(name, version, onupgradeneeded=undefined) {
return new Promise((resolve, reject) => {
"use strict";
const req = indexedDB.open(name, version);
req.onsuccess = (event) => void resolve(event.target.result);
req.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
req.onupgradeneeded = async (event) => {
try {
void await onupgradeneeded(event);
} catch (error) {
// If we allow this error to bubble, it will abort the upgrade,
// but it will be considered "uncaught" by the browser JS engine.
// Instead, we should abort the transaction ourselves and redirect
// the error to the caller of idb_open (where the browser could still
// complain -- correctly, in that case -- about it being "uncaught".)
try {
req.transaction.abort();
} catch (abort_error) {
if (abort_error instanceof InvalidStateError) {
abort_error.cause = error;
console.warn(abort_error);
} else {
debugger;
throw abort_error;
}
} finally {
reject(error);
}
}
};
});
}
async function idb_putOneItem(db, storeName, item, key=undefined) {
return new Promise(async (resolve, reject) => {
"use strict";
try {
const txn = db.transaction([storeName], 'readwrite');
txn.oncomplete = (event) => void resolve(result);
txn.onabort = txn.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
const store = txn.objectStore(storeName);
const result = await new Promise((resolve, reject) => {
try {
const req = (key !== undefined) ? store.put(item, key) : store.put(item);
req.onsuccess = (event) => void resolve(event.target.result);
req.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
} catch (error) {
txn.abort();
reject(error);
}
});
} catch (error) {
// async executor
reject(error);
}
});
}
async function idb_getOneItemByKey(db, storeName, key) {
return new Promise(async (resolve, reject) => {
"use strict";
try {
const txn = db.transaction([storeName], 'readwrite');
txn.oncomplete = (event) => void resolve(result);
txn.onabort = txn.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
const store = txn.objectStore(storeName);
const result = await new Promise((resolve, reject) => {
try {
const req = store.get(key);
req.onsuccess = (event) => void resolve(event.target.result);
req.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
} catch (error) {
txn.abort();
reject(error);
}
});
} catch (error) {
// async executor
reject(error);
}
});
}
async function idb_getOneItemByKeyStrict(db, storeName, key) {
return new Promise(async (resolve, reject) => {
"use strict";
try {
const txn = db.transaction([storeName], 'readwrite');
txn.oncomplete = (event) => void resolve(result);
txn.onabort = txn.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
const store = txn.objectStore(storeName);
const result = await new Promise((resolve, reject) => {
try {
const req = store.openCursor(key);
req.onsuccess = (event) => {
if (event.target.result !== null) {
resolve(event.target.result.value);
} else {
txn.abort();
reject(new Error('key not found', {cause: event}));
}
};
req.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
} catch (error) {
txn.abort();
reject(error);
}
});
} catch (error) {
// async executor
reject(error);
}
});
}
async function idb_deleteDb(name, options, onblocked) {
return new Promise((resolve, reject) => {
"use strict";
const req = indexedDB.deleteDatabase(...arguments);
req.onsuccess = (event) => void resolve(event);
req.onerror = (event) => void reject(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
req.onblocked = (onblocked !== undefined) ? onblocked : (event) => void console.warn(
new Error(`${event.target.__proto__.constructor.name}: ${event.type}`, {cause: event})
);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment