10

I have been working with IndexedDB for a bit now and I can successfully create a new database, create a store, and add a value during the "on upgrade needed". What I don't understand is, does the database remain "open" or do you have to re-open it inside of every function that needs access to read/write information in the database?

For example, here's my code (which works) to create a new database, and insert one record:

$(document).ready(function() {

var db;

function initDB() {
    console.log("opening db...");

    var req = indexedDB.open(dbName, version);
    req.onsuccess = function(event) {
      db = this.result;
      console.log("opening db is done");
    }

    req.onerror = function(event) {
      console.log("error opening db: ", event.target.errorCode);
    }

    req.onupgradeneeded = function(event) {
      db = event.target.result;
      var store = db.createObjectStore("creds", { autoincrement: true });
      store.add({ username:'none', password:'none'}, 1);
    }
  }

What is causing me confusion is, when I need to access the records in that database, or add more records, or delete records, I thought I could just create a new function and insert some values. This is what I have (which fails):

  function saveCreds() {
    usr = $("#username").val();
    psw = $("#password").val();

    $.getJSON(baseURL + "cred-check/?callback=?", { username:usr, password:psw }, function(data) {
      if (data.creds_good == 'true'); {
        // NEXT LINE FAILS
        var store = db.transaction(['creds'], 'readwrite').objectStore('creds');
        var request = store.get(1);
        request.onsuccess = function (event) {
          var data = request.result;
          data.username = usr;
          data.password = psw;

          var requestUpdate = store.put(data, 1);
          requestUpdate.onerror = function(event) {
            console.log("error putting value...");
          }
        }
      }
    });
  }

This saveCreds and the initDB function are inside the $(document).ready() function and the db variable is declared outside the initDB and saveCreds functions, but inside the $(document).ready() so I think my scope was OK.

The problem is, the db variable is undefined. I get the error: Cannot call method "transaction" of undefined.

So does this mean that for every function that needs access to the data in the database, I need to reopen it, and reassign it to a variable so I can manipulate/read data in the database?

Josh
  • 17,834
  • 7
  • 50
  • 68
Garfonzo
  • 3,876
  • 6
  • 43
  • 78

1 Answers1

5

My answer has to be: sometimes. No, you do not need to always open a new connection. You can use multiple transactions on a connection. A simple way to do this is to pass around the db variable to those functions. However, you must be aware of the asynchronous nature of javascript as well as indexedDB. There are times where you will need to open a new connection. For example, on the trigger of some other event.

So, if you are doing multiple transactions, use a large function something like the following:

function domultiplethings() {
  var db = ... 
  callfunction1(db);
  callfunction2(db);
}

function callfunction1(db) {
  if(!db) {
    // open a new connection then call ourself
  } else {
    // active connection, do read/write stuff
  }
}
Josh
  • 17,834
  • 7
  • 50
  • 68
  • This is kind of what I was thinking. But you're right, I'm running into issues with the asynchronous nature of javascript, which is fine. I guess a more precise question is: is it necessarily **bad** to open a new connection to the database multiple times, in multiple functions? – Garfonzo Jan 29 '14 at 04:43
  • I open connection for days, never been problem. I never close connection, but listen to version change event. In that case you must close. – Kyaw Tun Jan 29 '14 at 06:36
  • 1
    I have found that so far it is only bad practice to open a connection each time, but not bad performance. I looked under the hood at one point (you can see Joshua Bell's Google Chrome indexedDB implementation I think in C/C++), and from what I remember, there is connection pooling and automated connection closing (when no trans are open on a conn) after a timeout. In short, not "bad" just not great. – Josh Jan 29 '14 at 21:19
  • Also, do not use global db variables. You will just encounter problems. The examples that use a global db var are bad. See http://stackoverflow.com/questions/11898375/how-to-get-objectstore-from-indexeddb/16379163#16379163 – Josh Jan 29 '14 at 21:25