0

This is the code I have that wraps IndexedDb API in promises.

const asyncStorage = function(databaseName, storeName, version) {
    return new Promise((resolve, reject) => {
        const openRequest = window.indexedDB.open(databaseName, version)

        openRequest.onupgradeneeded = () => openRequest.result.createObjectStore(storeName)
        openRequest.onblocked = () => reject(new Error(`onblocked`))
        openRequest.onerror = () => reject(openRequest.error)
        openRequest.onsuccess = () => {
            const db = openRequest.result

            resolve((transactionType, fn) => runQueriesInTransaction({ db, storeName, transactionType, fn }))
        }
    });

    function runQueriesInTransaction({ db, storeName, transactionType, fn }) {
        return new Promise((resolve, reject) => {
            const transaction = db.transaction(storeName, transactionType)
            const store = transaction.objectStore(storeName)

            const requests = fn(store)

            const resultsPromise = Array.isArray(requests)
                ? Promise.all(requests.map(promisifyRequest))
                : promisifyRequest(requests)

            transaction.onerror = () => reject(transaction.error)
            transaction.oncomplete = () => resolve(resultsPromise)
        })
    }

    function promisifyRequest(request) {
        return new Promise((resolve, reject) => {
            request.onerror = err => {
                // prevent global error throw https://bugzilla.mozilla.org/show_bug.cgi?id=872873
                if (typeof err.preventDefault === `function`) {
                    err.preventDefault()
                }
                reject(request.error)
            }

            request.onsuccess = () => resolve(request.result)
        })
    }
};

The problem is getAll() seems to retrieve only the data in an array format, and getAllKeys() gets all the keys without the data. I could not find a method to get both keys and values. I currently loop through each key and get items in their own separate queries. Seems inefficient.

    const transaction = await asyncStorage('db', 'keyvaluepairs', 1);
    let keys = await transaction(`readonly`, idbStore => idbStore.getAllKeys());
    for (const key of keys)
        let json = await transaction(`readonly`, idbStore => idbStore.get(key));

I'm trying to convert my code from localStorage.

Bonus question: can I sort database results in descending order similar to SQL?

live627
  • 397
  • 4
  • 18
  • It seems you will need to use an [`IDBCursorWithValue`](https://developer.mozilla.org/en-US/docs/Web/API/IDBCursorWithValue) for this – Bergi Oct 17 '22 at 00:18
  • Suggest not wrapping every request in a promise. Only wrap the transaction in a promise. – Josh Oct 17 '22 at 06:39

0 Answers0