0

I have a promise which return an array of objects from IndexedDB:

const syncData = () => {
  return new Promise((resolve, reject)=>{
      var all_form_obj = [];
      var db = self.indexedDB.open('Test');
      db.onsuccess = function(event) {
          var db = this.result
          // Table new_form
          var count_object_store_new_form = this.result.transaction("new_form").objectStore("new_form").count()
          count_object_store_new_form.onsuccess = function(event) {
              if(count_object_store_new_form.result > 0){
                  db.transaction("new_form").objectStore("new_form").getAll().onsuccess = function(event) {
                    var old_form_arr = event.target.result
                    for(element in old_form_arr){
                        all_form_obj.push(old_form_arr[element])
                    }
                  }
              }
          }
          // Table old_form
          var count_object_store_old_form = this.result.transaction("old_form").objectStore("old_form").count()
          count_object_store_old_form.onsuccess = function(event) {
            if(count_object_store_old_form.result > 0){
              db.transaction("old_form").objectStore("old_form").getAll().onsuccess = function(event) {
                var old_form_arr = event.target.result
                for(element in old_form_arr){
                    all_form_obj.push(old_form_arr[element])
                }
              }
            }
          }
      }

      db.onerror = function(err) {
        reject(err);
      }
      resolve(all_form_obj)
  })
};

After I resolve my array, I call the promise in the sync event:

self.addEventListener('sync', function(event) {
  if (event.tag == 'sync_event') {
    event.waitUntil(
      syncData()
      .then((form_arr)=>{
        console.log(form_arr)
        for(form in form_arr) {
          console.log(form_arr)
        }
    }).catch((err) => console.log(err))
    );
  }
});

In the 'then' of my promise syncData I print to the console two times.
The first console.log appears in the console (my array of objects) but the second which is in loop (for in) doesn't appear in the console and I don't understand why.
My goal is to be able to loop through each object and send it to my database with fetch but the problem is that the code in the loop doesn't run.

My result of the first console log: enter image description here

sam
  • 95
  • 1
  • 2
  • 10

1 Answers1

0

I think resolve is not placed in the desired place and the reason why the 2nd console.log is not showing up is because form_arr is []. I simplified your code to demonstrate why it went []. db.onsuccess and db.onerror were just defined there without being called. To fix this problem, you may want to place resolve inside db.onsuccess and reject inside db.onerror.

const syncData = () => {
  return new Promise((resolve, reject)=>{
      var all_form_obj = [];
      var db = self.indexedDB.open('Test');
      db.onsuccess = function(event) {
        // ... will be called async

        resolve(all_form_obj)
      }

      db.onerror = function(err) {
        // ... will be called async
      }

      // remove resolve here
  })
};
hungdoansy
  • 436
  • 4
  • 10
  • `db.onsuccess` and `db.onerror` are automatically called when the indexedDB database is open without need to call them. The resolve is in the right place and in the first console log I get my array thus the problem is not here – sam Apr 22 '21 at 08:48
  • Alright. So may I ask you a few questions? When do you want to "resolve" the promise? It is when the database is open? What does the first console.log give you? Can you add it to the description? – hungdoansy Apr 22 '21 at 08:55
  • I put the resolve in the `db.onsuccess` and it doesn't change anything – sam Apr 22 '21 at 08:55
  • I want to resolve the promise when I get my array of objects from IndexedDB. – sam Apr 22 '21 at 08:57
  • Can you post what the first console.log printed? – hungdoansy Apr 22 '21 at 09:01
  • Yes I just put it on – sam Apr 22 '21 at 09:03
  • I see. If you type `[1, 2]` in the console and enter, you'd see `> (2) [1, 2]`. Here I see an empty array (`[]`), but it does have values (2 values). So I thought I might be right. The form_data was [] when it was printed out, but just in a matter of a second, it was updated by db.onsuccess. Can you try to put resolve like I did in the code (I edited)? – hungdoansy Apr 22 '21 at 09:14
  • I put the resolve as you advised me in the `db.onsuccess` but it doesn't change anything I get the same result (the photo I put now) – sam Apr 22 '21 at 09:18
  • Alright. What I have found is that form_data is [] (this is 100% sure because of the screenshot you posted). Because of that, 2nd console.log will be never get called because [] has no keys to iterate, so the for loop stops immediately. And it is likely that the resolve/reject is not running as expected. I found this article quite helpful https://medium.com/@_aakashpandey/understanding-indexeddb-and-creating-our-own-promise-based-api-19c425132d0c – hungdoansy Apr 22 '21 at 09:28
  • I also tried with foreach but it's the same, no result in the console. And about the article, I can't do like in the article because I need to get all the rows from the two objectStore (table) and only after this resolve the promise. – sam Apr 22 '21 at 09:39