0

I'm trying to take the values of a certain key from an indexed DB and add them to an array, this array works fine within the onsuccess function but is empty after it. I'm guessing by the order the two years[0] that are logged to the console appear that problem is something to do with being asynchronous. I'm obviously not really understanding what order things are happening in and how to achieve what I want. Could someone please help me understand what the problem is and maybe point me in the right direction to overcoming it.

// the array I want the values in
var years = new Array(); 

// function retrieves all objects between certain years, low and high
function getYears(low, high){  

var request = window.indexedDB.open("matchDB", 1);  
request.onerror = function(event) {console.log("onerror");}

request.onsuccess = function(event) {
var db = event.target.result;
var objectStore = db.transaction(["matches"], 'readonly').objectStore("matches");

var index = objectStore.index("year");
var range = IDBKeyRange.bound(low, high, true, true); 

var request = index.openCursor(range);
  request.onsuccess = function(evt) {
     var cursor = evt.target.result;
     if (cursor) {
        var matchList = cursor.value;
        // the value of the key year is pushed into the array years
        years.push(matchList.year);
        console.log(years[0]); // this works
        cursor.continue();
     }
  }
console.log(years[0]); //this is undefined
}
}
mao
  • 1,059
  • 2
  • 23
  • 43
  • 1
    Database access is asynchronous. Anything that depends on the result must be done in the `onsuccess` function. – Barmar Apr 05 '14 at 00:45
  • 1
    It's like AJAX, so see: http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call – Barmar Apr 05 '14 at 00:46

1 Answers1

2

request.onsuccess is a callback function that will get called when the asynchronous request has completed. Notice that you are just assigning a function to the onsuccess property, you are not executing the function. It could be executed seconds later.

The code following it will continue to be executed after it has been defined, so console.log(years[0]) will be called immediately after which is why it prints out "undefined" since the callback method hasn't been executed yet. All of your code that deals with "years" should go inside the callback.

If you don't want to shove all of your code inside the callback, just define another method and call it from within the callback method.

function handleRequest(evt) {
    var cursor = evt.target.result;
     if (cursor) {
        var matchList = cursor.value;
        // the value of the key year is pushed into the array years
        years.push(matchList.year);
        console.log(years[0]); // this works
        cursor.continue();
     }
}

var request = index.openCursor(range);
  request.onsuccess = function(evt) {
     handleRequest(evt);
  }
}
Jordan
  • 574
  • 1
  • 5
  • 15
  • Thanks for the explanation @Triad, I'm starting to understand it. So when I use index.openCursor(range) does that request several times until it matches all every object in the range? How would I then get something to run just once after it has finished? – mao Apr 05 '14 at 01:08
  • I'm not quite sure what the openCursor method does, but when that gets called the browser will run it off somewhere else asynchronously and the rest of your code continues as normal. All of the code could finish executing in fact, and then later on when that method finishes, it knows to call your callback method that you specified. It should only get called that one time, but I can't say for certain without seeing the openCursor method. Edit: It looks like you have a callback inside of a callback which could be why it is getting called more than once. – Jordan Apr 05 '14 at 01:26
  • thanks for the explanation again, I was able to run a function when the transaction completed using transaction.oncomplete = function () { – mao Apr 05 '14 at 01:37