Skip to content

Commit 943c971

Browse files
committed
minor
1 parent 29292c1 commit 943c971

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

2-ui/5-data-storage/03-indexeddb/article.md

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ The short answer is: we don't.
250250

251251
In the next version 3.0 of the specification, there will probably be a manual way to finish the transaction, but right now in 2.0 there isn't.
252252

253-
**When all transaction requests are finished, and the [microtasks queue](info:async-await#microtask-queue) is empty, it is committed automatically.**
253+
**When all transaction requests are finished, and the [microtasks queue](info:microtask-queue) is empty, it is committed automatically.**
254254

255255
```smart header="What's an \"empty microtask queue\"?"
256256
The microtask queue is explained in [another chapter](info:async-await#microtask-queue). In short, an empty microtask queue means that for all settled promises their `.then/catch/finally` handlers are executed.
@@ -431,7 +431,7 @@ So requests that return many values always return them in sorted by key order.
431431
```
432432

433433

434-
## Searching by indexes
434+
## Searching by any field with an index
435435

436436
To search by other object fields, we need to create an additional data structure named "index".
437437

@@ -643,17 +643,49 @@ try {
643643

644644
So we have all the sweet "plain async code" and "try..catch" stuff.
645645

646-
If we don't catch the error, then it falls through and finally becomes an "unhandled promise rejection" event on `window` object.
646+
### Error handling
647647

648-
We can handle them like this:
648+
If we don't catch the error, then it falls through, just as usual.
649+
650+
Ultimately, if uncaught, it becomes an "unhandled promise rejection" event on `window` object.
651+
652+
We can handle such errors like this:
649653

650654
```js
651655
window.addEventListener('unhandledrejection', event => {
652656
let request = event.target; // IndexedDB native request object
653657
let error = event.reason; // Unhandled error object, same as request.error
658+
...report about the error...
654659
});
655660
```
656661

662+
### "Inactive transaction" pitfall
663+
664+
As it was said, a transaction auto-commits as soon as the browser is done with the current code and microtasks.
665+
666+
So if we put an *macrotask* like `fetch` in the middle of a transaction, then the transaction won't wait for it to finish. It just auto-commits. So the next request in it fails.
667+
668+
Here's an example of `fetch` in the middle of the transaction:
669+
670+
```js
671+
let transaction = db.transaction("inventory", "readwrite");
672+
let inventory = transaction.objectStore("inventory");
673+
674+
await inventory.add({ id: 'js', price: 10, created: new Date() });
675+
676+
await fetch(...); // (*)
677+
678+
await inventory.add({ id: 'js', price: 10, created: new Date() }); // Error
679+
```
680+
681+
The next `inventory.add` after `fetch` `(*)` fails with an "inactive transaction" error, because the transaction is already committed and closed at that time.
682+
683+
The workaround is same as when working with native IndexedDB: either make a new transaction or just split things apart.
684+
1. Prepare the data and fetch all that's needed first.
685+
2. Then save in the database.
686+
687+
### Getting native objects
688+
657689
Internally, the wrapper performs a native IndexedDB request, adding `onerror/onsuccess` to it, and returns a promise that rejects/resolves with the result.
658690

659691
That works most fine of the time. The examples are at the lib page <https://github.com/jakearchibald/idb>.

0 commit comments

Comments
 (0)