Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions 6-data-storage/03-indexeddb/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,27 +149,27 @@ openRequest.onsuccess = function() {
};
*/!*

// ...база данных готова, используйте ее...
// ...база данных готова, используйте её...
};

*!*
openRequest.onblocked = function() {
// это событие не должно срабатывать, если мы правильно обрабатываем onversionchange
// этот обработчик не будет вызван, если мы правильно обрабатываем событие versionchange

// это означает, что есть ещё одно открытое соединение с той же базой данных
// и он не был закрыт после того, как для него сработал db.onversionchange
// и оно не было закрыто после возникновения события versionchange
};
*/!*
```

...Другими словами, здесь мы делаем две вещи:

1. Обработчик `db.onversionchange` сообщает нам о попытке параллельного обновления, если текущая версия базы данных устарела.
2. Обработчик `OpenRequest.onblocked` сообщает нам об обратной ситуации: в другом месте есть соединение с устаревшей версией, и оно не закрывается, поэтому новое соединение установить невозможно.
2. Обработчик `openRequest.onblocked` сообщает нам об обратной ситуации: в другом месте есть соединение с устаревшей версией, и оно не закрывается, поэтому новое соединение установить невозможно.

Мы можем более изящно обращаться с вещами в `db.onversionchange`, например предлагать посетителю сохранить данные до закрытия соединения и так далее.

Или альтернативным подходом было бы не закрывать базу данных в `db.onversionchange`, а вместо этого использовать обработчик `onblocked` (на новой вкладке), чтобы предупредить посетителя, что более новая версия не может быть загружена, пока они не закроют другие вкладки.
Или альтернативным подходом было бы не закрывать базу данных в `db.onversionchange`, а вместо этого использовать обработчик `onblocked` (на новой вкладке), чтобы предупредить посетителя, что более новая версия не может быть загружена, пока он не закроет другие вкладки.

Такой конфликт при обновлении происходит редко, но мы должны как-то его обрабатывать, хотя бы поставить обработчик `onblocked`, чтобы наш скрипт не "умирал" молча, удивляя посетителя.

Expand Down Expand Up @@ -381,7 +381,7 @@ request1.onsuccess = function() {

Сначала сделаем `fetch`, подготовим данные, если нужно, затем создадим транзакцию и выполним все запросы к базе данных.

Чтобы поймать момент успешного выполнения, мы можем повесить обработчик на событие `transaction.oncomplete`:
Чтобы поймать момент успешного выполнения, мы можем повесить обработчик на событие `complete`:

```js
let transaction = db.transaction("books", "readwrite");
Expand All @@ -401,7 +401,7 @@ transaction.oncomplete = function() {
transaction.abort();
```

Это отменит все изменения, сделанные запросами в транзакции, и сгенерирует событие `transaction.onabort`.
Это отменит все изменения, сделанные запросами в транзакции, и сгенерирует событие `abort`.


## Обработка ошибок
Expand Down Expand Up @@ -668,7 +668,7 @@ let request = store.openCursor([query], [direction]);
- `"prev"` -- обратный порядок: от самого большого ключа к меньшему.
- `"nextunique"`, `"prevunique"` -- то же самое, но курсор пропускает записи с тем же ключом, что уже был (только для курсоров по индексам, например, для нескольких книг с price=5, будет возвращена только первая).

**Основным отличием курсора является то, что `request.onsuccess` генерируется многократно: один раз для каждого результата.**
**Основным отличием курсора является то, что обработчик `request.onsuccess` вызывается многократно: один раз для каждого результата.**

Вот пример того, как использовать курсор:

Expand Down Expand Up @@ -760,21 +760,20 @@ try {

Если мы не перехватим ошибку, то она "вывалится" наружу, вверх по стеку вызовов, до ближайшего внешнего `try..catch`.

Необработанная ошибка становится событием "unhandled promise rejection" в объекте `window`.
Необработанная ошибка приводит к возникновению события `unhandledrejection` (unhandled promise rejection) на объекте `window`.

Мы можем обработать такие ошибки вот так:
Мы можем перехватить её следующим образом:

```js
window.addEventListener('unhandledrejection', event => {
let request = event.target; // объект запроса IndexedDB
let error = event.reason; // Необработанный объект ошибки, как request.error
let error = event.reason; // Объект ошибки, из-за которой отклонён промис
...сообщить об ошибке...
});
```

### Подводный камень: "Inactive transaction"

Как мы уже знаем, транзакции автоматически завершаются, как только браузер завершает работу с текущим кодом и макрозадачу. Поэтому, если мы поместим *макрозадачу* наподобие `fetch` в середину транзакции, транзакция не будет ожидать её завершения. Произойдёт автозавершение транзакции. Поэтому при следующем запросе возникнет ошибка.
Как мы уже знаем, транзакции автоматически завершаются, как только браузер заканчивает выполнение текущего синхронного кода и микрозадач. Поэтому, если мы поместим *макрозадачу* наподобие `fetch` в середину транзакции, транзакция не будет ожидать её завершения. Произойдёт автозавершение транзакции. Поэтому при следующем запросе возникнет ошибка.

Для промисифицирующей обёртки и `async/await` поведение такое же.

Expand Down