1
\$\begingroup\$

I'm a Web Development student, and I just started learning indexeddb a little while ago. At present my teacher hasn't taught us Promises, and I'm not really sure he plans to. So, I took the initiative and learned them myself. But as my teacher doesn't know or isn't teaching Promises, I wanted help reviewing my code to ensure that I am using best practices and that my is clean and well written.

Also, and the thing that I'm more focused on, is using the functional paradigm. When I started my degree, I made a point of learning it along the way. But now that I have to deal with databases and explicit stateliness I'm a bit at a loss. I did my best to maintain referential transparency and purity, but there's only so much I could do. I'd like to learn the functional approach to interacting with databases and the outside world in general.

The below code is functioning to the best of my knowledge. I coded it recently for my personal use (and practice), and it has passed all of my tests. But I haven't used it for an actual project yet, so I'm sure it has shortcomings.


returns a promise for an open link to the database:

function getDb(databaseName, version, upgradeDb) {
  return new Promise(function(resolve, reject) {
    const request = indexedDB.open(databaseName, version);
    request.onupgradeneeded = function(e) {
      if (upgradeDb) {
        /*
        This was really awkward. This whole function is dependent on the state
        of my database. Would it be better to use createDb and updateDb functions
        and then use this to only return the database?
        */
        upgradeDb(e.target.result);
        resolve(e.target.result);
      }
    }

    request.onsuccess = function(e) {
      resolve(e.target.result);
    };

    request.onerror = function(e) {
      reject(console.log("error"));
    }
  });
}


Short and sweat. More readable for me:

async function getObjectStore(db, objectStore, permissions) {
  return (await db).transaction([objectStore], permissions).objectStore(objectStore);
}


This one isn't strictly necesarry. And it'd be easier to just use objectStore.add() maybe. But I like it. Also, databases. State. Grr. What is a good way to manage I/O and stateliness when using the functional approach?:

async function addEntry(objectStore, object) {
  (await objectStore).add(object);
}


same as above:

async function deleteEntry(objectStore, keyRange) {
  (await objectStore).delete(keyRange);
}


This feels more awkward than maybe it should. It would be simpler to declare this as an async function and use await, but I don't know how to utilize resolve with that.:

function getEntries(objectStore, keyRange) {
  return new Promise(function(resolve, reject) {
    const request = (objectStore).then(x => x.getAll(keyRange));
    request.then(x => x.onsuccess = function(e) {
      resolve(e.target.result);
    });
  });
}


same as above:

function getEntry(objectStore, keyRange) {
  return new Promise(function(resolve, reject) {
    const request = (objectStore).then(x => x.get(keyRange));
    request.then(x => x.onsuccess = function(e) {
      resolve(e.target.result);
    });
  });
}


So this. I wanted it to be able to handle both inline and outline objectStore. This isn't really the most clean, because indexKey could be an object or a value. But I don't have the advantage of type declarations that I might have in other languages. It works for me, but is there a better solution?:

async function updateEntry(objectStore, indexKey, object) {
  if (typeof indexKey === Object) {
    const indexValue = Object.keys(indexKey)[0];
    const keyValue = indexKey[indexValue];
    const newObject = Object.assign({}, object, indexKey);
    const request = (await objectStore).get(keyValue);
    request.onsuccess = async function(e) {
      (await objectStore).put(newObject);
    };
  } else {
    const request = (await objectStore).get(indexKey);
    request.onsuccess = async function(e) {
      (await objectStore).put(object, indexKey);
    };
  }
}
\$\endgroup\$
  • \$\begingroup\$ Thank you. That was an oversight on my part. upgradeDb is a function that would build the database, it doesn't include resolve within it. I'll adjust my code. \$\endgroup\$ – Ucenna Nov 11 '17 at 22:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.