Miha Šušteršič
Miha Šušteršič

Reputation: 10062

IndexDB cursor .onsucess as a promise

First of all, I can't find a suitable title for this question - please feel free to edit.

I have the following function that reads objects from indexDb,

loadNeededParcels = property => {
    const dbResults = [];
    var readTransaction = this.db
      .transaction("parcelData")
      .objectStore("parcelData");
    readTransaction.openCursor().onerror = e => {
      console.log("open cursor error ", e);
    };
    readTransaction.openCursor().onsuccess = e => {
      const cursor = e.target.result;
      if (cursor) {
        dbResults.push(cursor.value);
        cursor.continue();
      } else {   
        return dbResults;
      }
    };
  };

Now when I call this function with a simple function call, for example:

console.log(loadNeededParcels('hasData'))

The console log is undefined. I am guessing this happens because the function does not wait for the cursor to finish and return the dbResults variable?

So my question is this - how can I re-write this function as a promise, or rather to wait for the readTransaction.openCursor().onsucess to trigger?

So the expected result is for the function to actually return the values read from the database before exiting.

I am using cursors since the .getAll() the method is not supported in IE.

Upvotes: 1

Views: 431

Answers (2)

Josh
Josh

Reputation: 18720

Try something like this. Do not call openCursor twice, that creates two requests.

function loadNeededParcels(db, property) {
 return new Promise(function(resolve, reject) {
   var results = [];
   var tx = db.transaction('parcelData');
   tx.onerror = function(event) {
     reject(tx.error);
   };
   var store = tx.objectStore('parcelData');

   // Open a cursor over all items
   var request = store.openCursor();

   request.onsuccess = function(event) {
     var cursor = request.result;
     if(cursor) {
       var value = cursor.value;
       if(value) {
         // Only append defined values to the array
         results.push(cursor.value);
       }

       cursor.continue();
     } else {
       resolve(results);
     }
   };
 });
}

loadNeededParcels(db, 'hasData').then(function(results) {
  console.log('Results', results);
}).catch(function(error) {
  console.error(error);
});

Upvotes: 2

Miha Šušteršič
Miha Šušteršič

Reputation: 10062

A simple solution that I ended up using:

  loadNeededParcels = property => {
    return new Promise((resolve, reject) => {
      var readTransaction = this.db
        .transaction("parcelData")
        .objectStore("parcelData");
      readTransaction.openCursor().onerror = e => {
        reject(e);
      };
      const dbResults = [];
      readTransaction.openCursor().onsuccess = e => {
        const cursor = e.target.result;
        if (cursor) {
          dbResults.push(cursor.value);
          cursor.continue();
        } else {
          resolve(dbResults);
        }
      };
    });
  };

Upvotes: 2

Related Questions