Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding JS objects to an array using a cursor loop

I'm trying to recreate a mySQL/PHP project of mine (a "new tab" style page storing bookmarks with accent colours, folders, and a speed dial / pinned section) in IndexedDB for a client-side storage solution (with hopes of moving it to a Chrome extension).

I like to think I have an OK understanding of JS, however I can't work out why the following is only returning an empty array. From what I can see the "response" array is declared at the begining of the function and should therefore be accessible by the subordinate functions therein. Sticking in console logs does indicate that the array is successfully being pushed to with the objects created by the cursor iterations, however once the cursor finishes, response is left empty.

// Specify index and key value OR omit for all
function getItems(ind,key) {
var response = [];
var transaction = db.transaction(["items"],"readonly");
var store = transaction.objectStore("items");

// If args are omitted - grab all items
if(!ind | !key) {
    var cursor = store.openCursor();
    cursor.onsuccess = function(e) {
        var res = e.target.result;
        if(res) {
            var r = {
                "name": res.value['name'],
                "url": res.value['url'],
                "folder": res.value['folder'],
                "colour": res.value['colour'],
                "dial": res.value['dial'],
                "order": res.value['order']
            };
            response.push(r);
            res.continue();
        }
        return response;
    }
} else {
    // If both args are specified query specified index
    store = store.index(ind);
    var range = IDBKeyRange.bound(key, key);
    store.openCursor(range).onsuccess = function(e) {
        var res = e.target.result;
        if(res) {
            var r = {
                "name": res.value['name'],
                "url": res.value['url'],
                "folder": res.value['folder'],
                "colour": res.value['colour'],
                "dial": res.value['dial'],
                "order": res.value['order']
            };
            response.push(r);
            res.continue();
        }
        return response;
    }
}
}

Am I being stupid and missing something here?

like image 594
Dean Kellham Avatar asked Mar 24 '26 02:03

Dean Kellham


1 Answers

When you write:

cursor.onsuccess = function(e) {
    ...
    return response;
}

You're returning a value from that anonymous event handler (which will be ignored). By the time this handler executes, the call to getItems() itself has long since completed. You can't simply return a value produced by an asynchronous operation like the cursor iteration.

Try this instead:

function getItems(callback, ind, key) {
  var response = [];
  var transaction = db.transaction(["items"],"readonly");
  var store = transaction.objectStore("items");
  transaction.oncomplete = function() { callback(response); };

  ...
}

And call it as:

getItems(function(response) {
  for (var i = 0; i < response.length; ++i) {
    console.log(response[i]);
  }
} /* ind, key */);
like image 120
Joshua Bell Avatar answered Mar 26 '26 16:03

Joshua Bell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!