question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Executing transactions in a for loop only executes one transaction and finishes

See original GitHub issue

I am trying to overload indexDB by inserting lots of 64 base images in a loop. However, the transaction in my loop executes only once. How can this be done?

const initIDB = async () => {
  const db = await openDB('db', 1, {
    // eslint-disable-next-line no-shadow
    upgrade(db) {
      db.createObjectStore('tempStore', { keyPath: 'id', autoIncrement: true });
    },
  });
  const tx = db.transaction('tempStore', 'readwrite');
  await overloadIDB(tx.store);
  await tx.done;


  return true;
};

const getRandomArbitrary = (min, max) => Math.random() * (max - min) + min;

const overloadIDB = async (store) => {
  const imgurl = "bla.png";
  const img64 = await toDataURL(imgurl);
  for (let i = 0; i < 10; i++) {
    if (i > 0 && i % 100 === 0) console.log('A set done');
    try {
      const num = Math.round(getRandomArbitrary(1, 1000000));
      const data = {
        id: num,
        img: img64,
      };
      await new Promise(resolve => resolve(store.add(data)));
    } catch (e) {
      console.log(e.toString());
      console.dir(e);
      break;
    }
  }
};

const toDataURL = url => new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.responseType = 'blob';
  xhr.onload = () => {
    const reader = new FileReader();
    reader.onloadend = () => {
      resolve((reader.result));
    };
    reader.readAsDataURL(xhr.response);
  };
  xhr.send();
});

Keep getting this error

Failed to execute 'add' on 'IDBObjectStore': The transaction has finished

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:14 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
jakearchibaldcommented, Oct 29, 2019

You’ll need to handle cases where something else alters the counter while you’re fetching. Here’s how I’d do it:

const originalVal = await db.get('keyval', 'counter');
const newVal = await getNewValSomeAsyncWay();
const tx = db.transaction('keyval', 'readwrite');
const val = await tx.store.get('counter');
if (val !== originalVal) {
  // The value has been changed while we were fetching
  tx.abort();
} else {
  tx.store.put(newVal, 'counter');
}
await tx.done; // This will throw if the transaction was aborted
1reaction
jakearchibaldcommented, Oct 28, 2019

Right now you’re creating a single transaction to do the read and the write, but it doesn’t work because you’ve got a fetch in the middle of it.

Instead, do the read in a transaction, then do the fetch, then do the write in a second transaction.

On Mon, 28 Oct 2019, 22:23 Rost Myshkin, notifications@github.com wrote:

Can you please elaborate?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jakearchibald/idb/issues/135?email_source=notifications&email_token=AAAW3GVLOD3MRFBHOA4M7KLQQ5Q5TA5CNFSM4JF7ZNPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECOSXBY#issuecomment-547171207, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAW3GWN7AIUXPX5PFHXKUDQQ5Q5TANCNFSM4JF7ZNPA .

Read more comments on GitHub >

github_iconTop Results From Across the Web

Behavior of a loop within a single TRANSACTION
As for the core question: transactions can use savepoints in such iterations, so that iteration 1-4 are saved (committed) even if iteration 5 ......
Read more >
sql server - Are explicit transactions needed in this while loop?
Individual statements -- DML, DDL, etc -- are transactions in themselves. So yes, after each iteration of the loop (technically: after each ...
Read more >
Debugging background tasks inside loops and transactions
A connection has an attribute called run_on_commit , which is just a list of tasks that will be added to the queue of...
Read more >
"COMMIT" should not be used inside a loop
Further, in general use COMMIT should only be used at the end of a transaction. Code that is not structured to have one...
Read more >
for Loop - an overview | ScienceDirect Topics
for loops, like while loops, repeatedly execute a block of code until a ... At the beginning of each iteration, the for loop...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found