jakearchibald / idb

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

"AbortError" when adding obj with key which already exists #263

Closed tanyaMel closed 2 years ago

tanyaMel commented 2 years ago

Hello! :)

I'm using this amasing package and writting unit tests to get sure that everything works fine. And I was surprised by an unexpected "AbortError". It occurs when adding an obj with key that already exists while should be just error "Key already exists in the object store".

Steps to reproduce: 1) set "keyPath" in store; 2) add first value with unique "keyPath" (there's no errors in console); 3) try to add another one with "keyPath" value from step 2; 4) check errors in console.

For example, I set action to always add object "{ position: "position", rate: "1600.58" }" on page button. In the store "keyPath" is "position". When I click first time everything is OK. But when I click second time and others - there's not only "Key already exists in the object store" that I expect but "AbortError". This error brokes my unit tests because I can't catch and handle it.

Here's console messages: image And the source: image

I create class to not use indexeddb directly. There's method add in this class. Here's code:

async add(storageName: string, obj: any) {
    const db = this.db
    const transaction = db.transaction(storageName, "readwrite")
    const storage = transaction.objectStore(storageName)
    await storage.add(obj)
    await transaction.done
  }

If I use just store.add not in class, like this:

      <button
        onClick={async () => {
          if (db) {
            const storageName = "rates"
            const obj = { position: "position", rate: "1600.58" }
            const transaction = db.transaction(storageName, "readwrite")
            const storage = transaction.objectStore(storageName)
            await storage.add(obj)
            await transaction.done
          } else {
            console.warn("The database is loading, wait.")
          }
        }}
      >
        add
      </button>

It's still occurs "AbotError".

What I'm doing wrong?

General technologies:

tanyaMel commented 2 years ago

I found how to catch "AbortError": instead of

    await storage.add(obj)
    await transaction.done

I wrote

await Promise.all([storage.add(obj), transaction.done]).

But I don't understand why it's work. In the first way code is waiting resolve/reject promises storage.add and transaction.done operations. And in the second way Promise.all waits the same.

Tell me please what did I miss?

UPD: I read about "Fail Fast". But... why I can't catch "AbortError" in the try/catch by this (it's still uncauth error):

...
            try {
              const storageName = "rates"
              const obj = { position: "position", rate: "1600.58" }
              const transaction = db.transaction(storageName, "readwrite")
              const storage = transaction.objectStore(storageName)
              await storage.add(obj)
              await transaction.done
            } catch (e) {
              console.error(e)
            }
...

image

tanyaMel commented 2 years ago

I'm sorry. I found answer in #256

Thank you so much for this package!