IndexedDB - How to read max id in object store

Viewed 160

I'm working on an a web app which reads data from the server and, for cost-saving purpose, needs to store data on the browser so that it can "incrementally" reads data from the server instead of reading them all every time, to reduce network usage.

What I have so far is:

  • a function to add an array to an existing object store:
function IXDBaddItems(osName, items, callback) {
  const tx = db.transaction([osName], "readwrite");
  const obj = tx.objectStore(osName);

  items.forEach(item => {
    obj.put(item);
  })

  tx.oncomplete = (event) => {
    callback();
  }
};
  • a function that makes incremental ajax call on the server having an argument "lastId", and finally store the results in the objectStore
const getCorsiLastId = (lastId) => {
  makeAjaxCall(urlCorsiVendite, "POST", {
      ultimoId: lastId
    })
    .then(
      (resp) => {
        resp.forEach(d => {
          d.id = +d.id;
          d.id_course = +d.id_course;
          d.id_user = +d.id_user;
          d.insert_Date = new Date(d.insert_Date);
          d.nome_corso = d.nome_corso;
          d.year = +d.insert_Date.getFullYear();
          d.month = +d.insert_Date.getMonth() + 1;
          d.ref = +d.ref;
        });
      IXDBaddItems('corsiVendite', resp, () => console.log('db corsi update completed'));
      },
      (err) => console.log(err)
    );
};
  • the "async main body":
let db;

(async () => {
  let request = window.indexedDB.open('dbKpiMarketing', 1);

  // onerror handler signifies that the database didn't open successfully
  request.onerror = (e) => {
    console.log(e);
  };

  // onsuccess handler signifies that the database opened successfully
  request.onsuccess = async(e) => {
    console.log('Database opened successfully');

    // Store the opened database object in the db variable. This is used a lot below
    db = request.result;

    getCorsiLastId(0);
  };

  // Setup the database tables if this has not already been done
  request.onupgradeneeded = (e) => {
    // Grab a reference to the opened database
    let db = e.target.result;

    // Create an objectStore to store our data
    let osCorsi = db.createObjectStore('corsiVendite', {
      keyPath: 'id'
    });
    let osServizi = db.createObjectStore('serviziVendite', {
      keyPath: 'id'
    });

    console.log('Database setup complete');
  };

})();

Right now I'm calling the ajax function with lastId=0 to get everything back. I need to make this dynamic. With these two lines of code in console i get what i'm looking for: the highest stored id.

let c = db.transaction('corsiVendite').objectStore('corsiVendite').getAll()
let lastIdCorsi = Math.max(...c.result.map(d=>d.id));

I need to take these two lines and run them before calling getCorsiLastId(LastIdCorsi) but if i try that I get an error: Uncaught (in promise) DOMException: Failed to read the 'result' property from 'IDBRequest': The request has not finished. I understand that the transaction takes some time so I can't use the result right after. How can I overcome this issue?

1 Answers

I think I solved it...I actually already did the right thing in the IXDBaddItems function using the oncomplete method of the transaction. I added these lines:

let t = db.transaction('corsiVendite', 'readwrite');
let o = t.objectStore('corsiVendite');
let c = o.getAll();
t.oncomplete = (e) => {
    LastId = Math.max(...c.result.map(d=>d.id));
};
Related