jakearchibald / idb

IndexedDB, but with promises
https://www.npmjs.com/package/idb
ISC License
6.29k stars 353 forks source link

Uncatchable AbortError when using shortcut methods #190

Closed filipesilva closed 3 years ago

filipesilva commented 4 years ago

Hi there 👋

I'm using the shortcut methods to add data to a store. One of the things I want to do is prevent double-adds on the same index. I have the following code to do it:

Live example: https://stackblitz.com/edit/typescript-gxz95r Code:

import { openDB } from "idb";

async function demo() {
  const dbName = "random-db-" + Math.random();
  const storeName = "store-name";
  // Open IDB and create store of unconfirmed txs
  const db = await openDB(dbName, 1, {
    upgrade(db) {
      const store = db.createObjectStore(storeName, {
        keyPath: "idb_t",
        autoIncrement: true
      });
      store.createIndex("idb_t", "idb_t", {
        unique: true
      });
    }
  });

  // add an item
  await db.add(storeName, { idb_t: 1 });

  // add it again
  try {
    await db.add(storeName, { idb_t: 1 });
  } catch (e) {
    // do nothing, this looks like the index preventing a double insert.
    // his still leaves an DOMException: AbortError thrown in the console
  }
}

demo();

If you open the console, there will be an Uncaught (in promise) DOMException: AbortError error.

Reading through the docs for this error, it looks like I'd have to add a handler on the transaction itself. But since the shortcut method handles that for me, I don't think I can do that.

Is there a way to still use the shortcut methods and also catch AbortError?

filipesilva commented 4 years ago

For comparison, here is the version that catches both errors separately https://stackblitz.com/edit/typescript-w4dgtg?file=index.ts

import { openDB } from "idb";

async function demo() {
  const dbName = "random-db-" + Math.random();
  const storeName = "store-name";
  // Open IDB and create store of unconfirmed txs
  const db = await openDB(dbName, 1, {
    upgrade(db) {
      const store = db.createObjectStore(storeName, {
        keyPath: "idb_t",
        autoIncrement: true
      });
      store.createIndex("idb_t", "idb_t", {
        unique: true
      });
    }
  });

  // add an item
  var tx = db.transaction(storeName, 'readwrite');
  var store = tx.objectStore(storeName);
  store.add({ idb_t: 1 });
  await tx.done;

  // add it again
  try {
    var tx = db.transaction(storeName, 'readwrite');
    var store = tx.objectStore(storeName);
    try {
      await store.add({ idb_t: 1 });
    } catch (e) {
      // do nothing, this looks like the index preventing a double insert.
      console.log(e)  
    }
    await tx.done;
  } catch (e) {
    // ignore the AbortError resulting from the add failing.
    console.log(e)
  }
}

demo();
jakearchibald commented 4 years ago

Thanks for reporting this. I'll take a look.

matheusrgarcia commented 3 years ago

Any news on this?

jakearchibald commented 3 years ago

Hoping to find time to fix this and some other issues towards the end of the year.

jakearchibald commented 3 years ago

Thanks for the report. This will be fixed in the next release.