You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 6-data-storage/03-indexeddb/article.md
+19-7Lines changed: 19 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -193,13 +193,12 @@ A key must be one of these types - number, date, string, binary, or array. It's
193
193
194
194

195
195
196
-
197
196
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.
198
197
199
198
But we need to create an object store first.
200
199
201
-
202
200
The syntax to create an object store:
201
+
203
202
```js
204
203
db.createObjectStore(name[, keyOptions]);
205
204
```
@@ -214,6 +213,7 @@ Please note, the operation is synchronous, no `await` needed.
214
213
If we don't supply `keyOptions`, then we'll need to provide a key explicitly later, when storing an object.
215
214
216
215
For instance, this object store uses `id` property as the key:
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.
224
224
225
225
To perform a database version upgrade, there are two main approaches:
226
+
226
227
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).
227
228
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.
-`readwrite` -- can only read and write the data, but not create/remove/alter object stores.
278
279
279
-
There's also `versionchange` transaction type: such transactions can do everything, but we can't create them manually. IndexedDB automatically creates a `versionchange` transaction when opening the database, for `updateneeded` handler. That's why it's a single place where we can update the database structure, create/remove object stores.
280
+
There's also `versionchange` transaction type: such transactions can do everything, but we can't create them manually. IndexedDB automatically creates a `versionchange` transaction when opening the database, for `upgradeneeded` handler. That's why it's a single place where we can update the database structure, create/remove object stores.
280
281
281
282
```smart header="Why are there different types of transactions?"
282
283
Performance is the reason why transactions need to be labeled either `readonly` and `readwrite`.
@@ -614,6 +615,7 @@ The `delete` method looks up values to delete by a query, the call format is sim
614
615
-**`delete(query)`** -- delete matching values by query.
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.
776
778
777
-
778
779
For a promise wrapper and `async/await` the situation is the same.
779
780
780
781
Here's an example of `fetch` in the middle of the transaction:
The next `inventory.add` after `fetch``(*)` fails with an "inactive transaction" error, because the transaction is already committed and closed at that time.
794
795
795
796
The workaround is the same as when working with native IndexedDB: either make a new transaction or just split things apart.
797
+
796
798
1. Prepare the data and fetch all that's needed first.
797
799
2. Then save in the database.
798
800
@@ -826,3 +828,13 @@ The basic usage can be described with a few phrases:
826
828
1. Get a promise wrapper like [idb](https://github.com/jakearchibald/idb).
827
829
2. Open a database: `idb.openDb(name, version, onupgradeneeded)`
828
830
- Create object storages and indexes in `onupgradeneeded` handler or perform version update if needed.
831
+
3. For requests:
832
+
- Create transaction `db.transaction('books')` (readwrite if needed).
833
+
- Get the object store `transaction.objectStore('books')`.
834
+
4. Then, to search by a key, call methods on the object store directly.
835
+
- To search by an object field, create an index.
836
+
5. If the data does not fit in memory, use a cursor.
0 commit comments