Skip to content

Commit d859d47

Browse files
authored
Merge pull request #3011 from Rnbsov/patch-48
👾 smth
2 parents 82f42cf + 9cceef1 commit d859d47

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

6-data-storage/03-indexeddb/article.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,12 @@ A key must be one of these types - number, date, string, binary, or array. It's
193193

194194
![](indexeddb-structure.svg)
195195

196-
197196
As we'll see very soon, we can provide a key when we add a value to the store, similar to `localStorage`. But when we store objects, IndexedDB allows setting up an object property as the key, which is much more convenient. Or we can auto-generate keys.
198197

199198
But we need to create an object store first.
200199

201-
202200
The syntax to create an object store:
201+
203202
```js
204203
db.createObjectStore(name[, keyOptions]);
205204
```
@@ -214,6 +213,7 @@ Please note, the operation is synchronous, no `await` needed.
214213
If we don't supply `keyOptions`, then we'll need to provide a key explicitly later, when storing an object.
215214

216215
For instance, this object store uses `id` property as the key:
216+
217217
```js
218218
db.createObjectStore('books', {keyPath: 'id'});
219219
```
@@ -223,6 +223,7 @@ db.createObjectStore('books', {keyPath: 'id'});
223223
That's a technical limitation. Outside of the handler we'll be able to add/remove/update the data, but object stores can only be created/removed/altered during a version update.
224224

225225
To perform a database version upgrade, there are two main approaches:
226+
226227
1. We can implement per-version upgrade functions: from 1 to 2, from 2 to 3, from 3 to 4 etc. Then, in `upgradeneeded` we can compare versions (e.g. old 2, now 4) and run per-version upgrades step by step, for every intermediate version (2 to 3, then 3 to 4).
227228
2. Or we can just examine the database: get a list of existing object stores as `db.objectStoreNames`. That object is a [DOMStringList](https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#domstringlist) that provides `contains(name)` method to check for existance. And then we can do updates depending on what exists and what doesn't.
228229

@@ -242,7 +243,6 @@ openRequest.onupgradeneeded = function() {
242243
};
243244
```
244245

245-
246246
To delete an object store:
247247

248248
```js
@@ -256,6 +256,7 @@ The term "transaction" is generic, used in many kinds of databases.
256256
A transaction is a group of operations, that should either all succeed or all fail.
257257

258258
For instance, when a person buys something, we need to:
259+
259260
1. Subtract the money from their account.
260261
2. Add the item to their inventory.
261262

@@ -614,6 +615,7 @@ The `delete` method looks up values to delete by a query, the call format is sim
614615
- **`delete(query)`** -- delete matching values by query.
615616

616617
For instance:
618+
617619
```js
618620
// delete the book with id='js'
619621
books.delete('js');
@@ -632,6 +634,7 @@ request.onsuccess = function() {
632634
```
633635

634636
To delete everything:
637+
635638
```js
636639
books.clear(); // clear the storage.
637640
```
@@ -651,6 +654,7 @@ Cursors provide the means to work around that.
651654
As an object store is sorted internally by key, a cursor walks the store in key order (ascending by default).
652655

653656
The syntax:
657+
654658
```js
655659
// like getAll, but with a cursor:
656660
let request = store.openCursor(query, [direction]);
@@ -748,7 +752,6 @@ try {
748752
} catch(err) {
749753
console.log('error', err.message);
750754
}
751-
752755
```
753756

754757
So we have all the sweet "plain async code" and "try..catch" stuff.
@@ -771,10 +774,8 @@ window.addEventListener('unhandledrejection', event => {
771774

772775
### "Inactive transaction" pitfall
773776

774-
775777
As we already know, a transaction auto-commits as soon as the browser is done with the current code and microtasks. So if we put a *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 would fail.
776778

777-
778779
For a promise wrapper and `async/await` the situation is the same.
779780

780781
Here's an example of `fetch` in the middle of the transaction:
@@ -793,6 +794,7 @@ await inventory.add({ id: 'js', price: 10, created: new Date() }); // Error
793794
The next `inventory.add` after `fetch` `(*)` fails with an "inactive transaction" error, because the transaction is already committed and closed at that time.
794795

795796
The workaround is the same as when working with native IndexedDB: either make a new transaction or just split things apart.
797+
796798
1. Prepare the data and fetch all that's needed first.
797799
2. Then save in the database.
798800

0 commit comments

Comments
 (0)