2

I have created many, let's say three ObjectStores inside a defined and versioned IndexedDB schema.

I need to populate all of them. To do so, I created an object which stores both name end endpoint (where it gets data to populate). Also to avoid error when trying to fill objectstores already populated, I use the count() method to ... count key inside the objectstore and if there are 0 key, then populates, else reads.

It works perfect if I execute on a one by one basis, that is instead of using a loop, declare and execute each one of the three objectstores.

However when invoking the function to populate each storage inside a loop, I get the following error message for the last two objectstores to be populated:

Failed to read the 'result' property from 'IDBRequest': The request has not finished. at IDBRequest.counts.(anonymous function).onsuccess

Here is the code:

 // object contains oject stores and endpoints.
 const stores = [
 {osName:'user-1', osEndPoint:'/api/1,
 {osName:'user-2', osEndPoint:'/api/2},
 {osName:'user-3', osEndPoint:'/api/3}
 ]; 

 // open db.
 var request = indexedDB.open(DB_NAME, DB_VERSION);

 // in order to dynamically create vars, instantiate two arrays.
 var tx = [];
 var counts = [];
 var total = [];

 // onsuccess callback.
 request.onsuccess = function (e) {
    db = this.result;
    for(k in stores) {
      tx[k] = db.transaction(stores[k].osName).objectStore(stores[k].osName);
      counts[k] = tx[i].count();
      counts[k].onsuccess = function(e) {
        total[k] = e.target.result;

     // if the counting result equals 0,  then populate by calling a function that does so.
      if (total[k] == 0) {                 
          fetchGet2(stores[k].osEndPoint, popTable, stores[k].osName); //
       } else { 
           readData(DB_NAME, DB_VERSION, stores[0].osName);
           } 
        };
         }   // closes for loop
     }; // closes request.onsuccess.

The fetchGet2 function works well inside a loop, for example the loop used to create the objectstores, and also has been tested on a one by one basis.

It looks like an async issue, however I cannot figure how to fix the problem which is to be able to populate existing objectstores dynamically, avoiding to populate filled objectsores and only filling empty ones.

Indeed testing without the count issue, but inside the loop works perfect, or with the count but without loop.

At the moment and when logging counts[k], It only logs data for the last member of the object.

Thanks in advance, I'm coding with vanilla js, and I'm not interested in using any framework at all.

2
  • You're not by any chance using the variable i anywhere else in your code? As written, this is using a global i variable. If fetchGet2 used i, for example, then i might be incremented and hence the request held in counts[i] is not the one that just fired the success event. Consider logging i within the onsuccess handler. Also, consider using counts[i].onsuccess = function(e) { and checking that counts[i] === e.target.result Your logic as presented here looks fine otherwise. Commented Feb 13, 2017 at 17:32
  • @JoshuaBell, I've tested changing the i var for k, indeed realized that no i is udes elsewhere in the namespace and also tested using counts[k].onsucceed = function(e) {}. However I get the same result: only executes the las element of the object, and when logging counts value and object name, only the last element is logged. Commented Feb 14, 2017 at 17:15

1 Answer 1

2

Yes, this looks like an issue with async. For loops iterate synchronously. Try writing a loop that does not advance i until each request completes.

Sign up to request clarification or add additional context in comments.

2 Comments

when iterating the loop without the count function, it works well, the problem is count ().
Thanks @Josh for the inspiration! A good simple effective example of such loop is provided here: stackoverflow.com/questions/14408718/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.