Storing the db object globally after an open

33 views
Skip to first unread message

Raymond Camden

unread,
Jan 29, 2015, 9:42:37 AM1/29/15
to indexed...@googlegroups.com
A user on this SO post (http://stackoverflow.com/questions/28168113/dbopenrequest-events-do-not-fire/28177238?noredirect=1) noted that it was a bad idea to copy the db object globally in your open event.

I think he is wrong (see our discussion in comments), but I wanted to see what others though.

Joshua Froelich

unread,
Jan 30, 2015, 1:03:45 AM1/30/15
to indexed...@googlegroups.com
Well, we can have a polite discussion about it here, right? If I am wrong I want to know why so I can learn. I am fairly certain I understand how it works right now. I'm wondering if its just poor communication.

Let's say you have the following code: var global = null; setTimeout(function() { global = 'hello'; }, 5); console.log(global);. The typical issue is that undefined is logged as global is not yet set at the time it is logged. The question is, then, how can/would you wait until it is defined?

Let's say you have the following: var db = null; var r = indexedDB.open(..); r.onsuccess = function(e) { db = e.target; }. console.log(db);.  The typical issue is that db is not yet set at the time it is logged. The question is, then, how can/would you wait until it is defined?

There are obviously hacks. We could timeout for x milliseconds before trying to use db. We could open the db every time the page loads, as the first thing, and not do anything else on page load that involves the db, thereby nearly guaranteeing that db is defined by the time it is used.

There are obviously times where it is ok to read/write to a variable in an outer scope from within a function. For example: 

function(callback) {
  var array = [];
  var tx = ...
  var store = tx.objectStore();
  var r = store.openCursor();
  tx.oncomplete = function() {
    // access and use the variable in outer scope by passing it to some other function
    callback(array);
  };
  r.onsuccess = function() {
   var cursor = event.target.result;
   if(!cursor) return;

   // access the variable in the outer scope and update it
   array.push(cursor.value);
   cursor.continue();
  }
}

Now, this works, and this is fine. Perfectly fine to read/write variables in an outer scope. No argument here. If you think this is what I am talking about then this is miscommunication.

What I am talking about exclusively is storing the db instance in an outer scope scope. It 'works' like I said on stackoverflow when you know what you are doing. For example, as I said above, when you always open it before everything else in some hackish fashion, or ensure the rest of the code 'waits' such that it runs at a later point in time (such on the next event loop at the earliest).

Here is a related point. Do you know if browsers guarantee the connection stays alive indefinitely? It doesn't look like keep-alive is spec-mandated so a browser could easily not bother to comply. So what happens when it closes? Now your db var is no longer 'open'. How does the rest of your app react?

Again, this is all meant to be a polite discussion. I would love to learn more if I misunderstand something. I do not do this professionally, just an evening hobby.

Dale Harvey

unread,
Jan 30, 2015, 5:19:42 AM1/30/15
to indexed...@googlegroups.com
It isnt wrong to assign the db object to a variable outside of the scope of onsuccess, its a very normal thing to do. it most certainly wont cause any issues with accessing the db object


> We could open the db every time the page loads, as the first thing, and not do anything else on page load > that involves the db, thereby nearly guaranteeing that db is defined by the time it is used.

This isnt a hack, this is very standard practice, you dont have to open the db on page load, but if you are going to use it you usually may as well do it early, and you do have to make sure that you dont attempt to use the database until it has complete instantiating.


> Here is a related point. Do you know if browsers guarantee the connection stays alive
> indefinitely? It doesn't look like keep-alive is spec-mandated so a browser could easily
> not bother to comply. So what happens when it closes? Now your db var is no longer
> 'open'. How does the rest of your app react?

keep-alive isnt related, thats just for http, generally the browser will maintain the db connection for the lifetime of the page, there is an 'onblocked' event if you have concurrent db (multiple tabs) and one of them attempts to do a schema upgrade, there is some more info about it @ https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB

Your example should and does work fine, I would take it out of the window.onload callback, if you go to http://paste.pouchdb.com/paste/bejju3/ and click view output you should see the onsuccess callback.

--
You received this message because you are subscribed to the Google Groups "IndexedDB Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to indexeddb-use...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Raymond Camden

unread,
Jan 30, 2015, 6:35:14 AM1/30/15
to indexed...@googlegroups.com
I think I see the confusion here (and I don't mean *your* confusion,
the confusion between you and I :).

You are absolutely right in your example of knowing when it is safe to use db.

In my demos, I do not allow the user to work with the db until a
success open event. So for example, if the demo lets you
add/edit/delete "note" objects, I don't allow for those operations to
follow until the application has properly started up.

As an example, http://code.tutsplus.com/tutorials/working-with-indexeddb--net-34673,
I simply start listening for events related to editing *after* the db
has succcessfully opened up.

"Do you know if browsers guarantee the connection stays alive indefinitely?"

This I do not know. I've never seen it close though. Again, I'd ask -
given an app that does basic CRUD, would you really call an open every
single time?


On Fri, Jan 30, 2015 at 12:03 AM, Joshua Froelich
<joshua....@gmail.com> wrote:
> Well, we can have a polite discussion about it here, right? If I am wrong I
> want to know why so I can learn. I am fairly certain I understand how it
> works right now. I'm wondering if its just poor communication.
>
>
> Here is a related point. Do you know if browsers guarantee the connection
> stays alive indefinitely? It doesn't look like keep-alive is spec-mandated
> so a browser could easily not bother to comply. So what happens when it
> closes? Now your db var is no longer 'open'. How does the rest of your app
> react?
>
> Again, this is all meant to be a polite discussion. I would love to learn
> more if I misunderstand something. I do not do this professionally, just an
> evening hobby.
>
> On Thursday, January 29, 2015 at 9:42:37 AM UTC-5, Raymond Camden wrote:
>>
>> A user on this SO post
>> (http://stackoverflow.com/questions/28168113/dbopenrequest-events-do-not-fire/28177238?noredirect=1)
>> noted that it was a bad idea to copy the db object globally in your open
>> event.
>>
>> I think he is wrong (see our discussion in comments), but I wanted to see
>> what others though.
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "IndexedDB Users" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/indexeddb-users/13fcrs1LH54/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
--
===========================================================================
Raymond Camden, Web Standards Evangelist

Email : raymon...@gmail.com
Blog : www.raymondcamden.com
Twitter: raymondcamden

Dale Harvey

unread,
Jan 30, 2015, 7:53:18 AM1/30/15
to indexed...@googlegroups.com
A common solution to readiness is

var db;

function useDB(callback) {
  if (db) {
    return callback(db);
  }
  // else do open stuff
  req.onsuccess = function(event) {
    db = event.target;
    callback(db);
  };
}

and have your client code always go via

useDB(function(db) {
   // do stuff
});



--

You received this message because you are subscribed to the Google Groups "IndexedDB Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to indexeddb-use...@googlegroups.com.

Josh

unread,
Jan 30, 2015, 3:18:09 PM1/30/15
to indexed...@googlegroups.com
In my demos, I do not allow the user to work with the db until a
success open event. ..., I don't allow for those operations to
follow until the application has properly started up.

Right, that's the issue. You know what you are doing, and it works in your app. But I would prefer not to advise newer programmers to follow. The spec's example, the Mozilla examples, and the html5rocks examples are all bad because of this pattern.  Which is why I see a new stackoverflow question every week asking why 'db' is null/undefined or why 'db.transaction...' throws an error and so forth. I am trying to avoid having newer programmers learn this tactic. Because it is certainly a hack. You are mixing in several concepts when you do this and provide this as an answer to someone, and I think most of those concepts are particularly confusing to newer JS devs, of which there are a ton.

 
This I do not know. I've never seen it close though. Again, I'd ask -
given an app that does basic CRUD, would you really call an open every
single time?

Yes. Maybe it is my background with JDBC connection pooling that makes it seem perfectly normal. indexedDB.open is basically just the first function in async.waterfall (caolin's lib on github). It is also to ensure correctness (e.g. there is never a time when db is undefined). I also prefer to keep variables as local as possible. I also prefer to let the variable head to GC when I am done at the end of a function (again, assuming that browsers eventually close the db and release the var). Those are all conventions and preference. 

The issue still is that this is not a good way to introduce newer programmers to indexedDB. You could argue that it would be easier to understand, but in fact, it is harder.

Raymond Camden

unread,
Jan 30, 2015, 3:35:40 PM1/30/15
to indexed...@googlegroups.com
Josh, thanks for taking the time to discuss this more. I think it's
fair to say I don't agree with you here, but as I said, I appreciate
you taking the time to help me understand where you're coming from at
least.

On Fri, Jan 30, 2015 at 2:18 PM, Josh <joshua....@gmail.com> wrote:
>> In my demos, I do not allow the user to work with the db until a
>> success open event. ..., I don't allow for those operations to
>> follow until the application has properly started up.
>
>
> Right, that's the issue. You know what you are doing, and it works in your
> app. But I would prefer not to advise newer programmers to follow. The
> spec's example, the Mozilla examples, and the html5rocks examples are all
> bad because of this pattern. Which is why I see a new stackoverflow
> question every week asking why 'db' is null/undefined or why
> 'db.transaction...' throws an error and so forth. I am trying to avoid
> having newer programmers learn this tactic. Because it is certainly a hack.
> You are mixing in several concepts when you do this and provide this as an
> answer to someone, and I think most of those concepts are particularly
> confusing to newer JS devs, of which there are a ton.
>
>


Dale Harvey

unread,
Jan 31, 2015, 2:14:39 PM1/31/15
to indexed...@googlegroups.com
I would suggest new programmers avoid indexeddb entirely, it could do with a lot of improvements from most perspectives but aiming towards a programmer unfamiliar with javascript I would imagine its entirely incomprehensible.

However even approaching a programmer new to JS, eschewing the common idioms and standard practices in favour of a dogmatic 'functional' approach is in my opinion going to produce more confusion, copying the db object into a global / app scope is the common way to do thing both in examples and real world code. 

In particular the comment

  1. The line db = DBOpenRequest.result appears to be assigning a value (the instance of an IDBDatabase object) that is only valid within the scope of the function to a variable defined in an outer scope where it is no longer valid. This signals a lack of experience with writing and using async code. You should probably learn more about async code before continuing.

Is straight up wrong and is certain to cause confusion

--

You received this message because you are subscribed to the Google Groups "IndexedDB Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to indexeddb-use...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages