Last active
April 11, 2024 17:06
-
-
Save JamesTheAwesomeDude/87dacf390eadf469e7200928c115e182 to your computer and use it in GitHub Desktop.
async indexedDB wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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