Skip to content
Merged

Sync #299

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a4ba2bb
close #2534 by slightly changing 7-microtask-queue
hamirmahal Mar 26, 2021
a662e1c
typo
joaquinelio Mar 27, 2021
67230aa
code
joaquinelio Mar 28, 2021
32eb2f9
typo
joaquinelio Mar 28, 2021
4820b97
repeated word
joaquinelio Mar 28, 2021
01ebc30
typo
joaquinelio Mar 28, 2021
c06e21f
Few grammatical corrections
VenkataPavan2494 Mar 31, 2021
6d0b314
Fix grammatical error
tamiolaf Apr 1, 2021
c722cda
Update article.md
PhilipKirner Apr 1, 2021
334d4de
pseudo function expression
lumosmind Apr 4, 2021
023ec22
typos
joaquinelio Apr 5, 2021
b896887
Fix comma splice.
m4ttsch Apr 5, 2021
a2c36c9
Fix plural typo line 414
dylan-workhub Apr 9, 2021
6de9d70
typo
joaquinelio Apr 11, 2021
dbae68c
Plunker reminder #1775
joaquinelio Apr 11, 2021
8b7bf10
store vs keeps stored
joaquinelio Apr 12, 2021
9e52cf3
Merge pull request #2578 from joaquinelio/patch-15
iliakan Apr 12, 2021
d8be8b0
Add scrollX/scrollY
iliakan Apr 15, 2021
2b33873
Merge pull request #2577 from joaquinelio/patch-14
iliakan Apr 17, 2021
3d8ab89
Merge pull request #2575 from joaquinelio/patch-13
iliakan Apr 17, 2021
35d1c85
Merge pull request #2573 from dylan-workhub/patch-1
iliakan Apr 17, 2021
adb962b
closes #2572
iliakan Apr 17, 2021
09c3914
Merge pull request #2568 from m4ttsch/patch-1
iliakan Apr 17, 2021
362e9a9
Merge pull request #2566 from joaquinelio/patch-11
iliakan Apr 17, 2021
4742c7b
Merge pull request #2565 from lumosmind/patch-8
iliakan Apr 17, 2021
8c5d3bf
Merge pull request #2562 from PhilipKirner/patch-1
iliakan Apr 17, 2021
4092b7f
Merge pull request #2561 from tamiolaf/patch-1
iliakan Apr 17, 2021
8be1642
Merge pull request #2559 from VenkataPavan2494/patch-1
iliakan Apr 17, 2021
ba0b184
Merge pull request #2558 from joaquinelio/patch-9
iliakan Apr 17, 2021
a18c710
Merge pull request #2557 from joaquinelio/patch-8
iliakan Apr 17, 2021
1b4b347
Merge pull request #2556 from joaquinelio/patch-7
iliakan Apr 17, 2021
4b10919
Merge pull request #2550 from hamirmahal/feat/update-readability-of-7…
iliakan Apr 17, 2021
e8a1cd8
Merge pull request #2552 from joaquinelio/patch-4
iliakan Apr 17, 2021
870a88c
Merge pull request #2554 from joaquinelio/patch-5
iliakan Apr 17, 2021
ffd8e03
typos? easier reading - review pls
joaquinelio Apr 18, 2021
6ab384f
Merge pull request #2584 from joaquinelio/patch-7
iliakan Apr 18, 2021
f0ab4a7
Merge branch 'master' of https://github.com/javascript-tutorial/en.ja…
pasor1 Apr 19, 2021
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
12 changes: 6 additions & 6 deletions 1-js/02-first-steps/15-function-basics/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ showMessage('Ann', "What's up?"); // Ann: What's up? (**)

Quando la funzione viene chiamata nelle righe `(*)` e `(**)`, il valore passato viene copiato nelle variabili locali `from` e `text`, che verranno utilizzate nella chiamata ad `alert`.

Guardiamo un altro esempio: abbiamo una variabile `from` e la passiamo a una funzione. Da notare: la funzione cambia `from`, ma il cambiamento non è visibile all'esterno perchè la funzione usa sempre una copia del valore passato:
Guardiamo un altro esempio: abbiamo una variabile `from` e la passiamo a una funzione. Da notare: la funzione cambia `from`, ma il cambiamento non è visibile all'esterno perché la funzione usa sempre una copia del valore passato:


```js run
Expand Down Expand Up @@ -232,7 +232,7 @@ function showMessage(text) {
showMessage(); // empty message
```

...Oppure utilizare l'operatore `||`:
...Oppure utilizzare l'operatore `||`:

```js
function showMessage(from, text) {
Expand Down Expand Up @@ -342,7 +342,7 @@ Per espressioni lunghe dopo la direttiva `return`, si potrebbe essere tentati da
return
(some + long + expression + or + whatever * f(a) + f(b))
```
Questo non funziona, perchè JavaScript interpreta un punto e virgola dopo `return`. E' come se dopo `return` ci fosse scritto:
Questo non funziona, perché JavaScript interpreta un punto e virgola dopo `return`. E' come se dopo `return` ci fosse scritto:

```js
return*!*;*/!*
Expand Down Expand Up @@ -370,7 +370,7 @@ Esempi di nomi:

```js no-beautify
showMessage(..) // mostra un messaggio
getAge(..) // ritonra l'età (prendendola da qualche parte)
getAge(..) // ritorna l'età (prendendola da qualche parte)
calcSum(..) // calcola la somma e ritorna il risultato
createForm(..) // crea un form (e solitamente lo ritorna)
checkPermission(..) // controlla i permessi, ritorna true/false
Expand All @@ -397,14 +397,14 @@ Funzioni che vengono utilizzate *molto spesso* potrebbero avere nomi molto corti

Ad esempio il framework [jQuery](http://jquery.com) definisce una funzione con `$`. La libreria [Lodash](http://lodash.com/) ha nel *core* una funzione denominata `_`.

Queste sono eccezioni. Generalmente i nomi delle funzioni sono precisi e descrittivi.
Queste sono eccezioni. Generalmente i nomi delle funzioni dovrebbero essere concisi e descrittivi.
```

## Funzioni == Commenti

Le funzioni dovrebbero essere brevi ed eseguire un solo compito. Se invece risultano lunghe, forse varrebbe la pena spezzarle in funzioni più piccole. Qualche volta può non essere semplice seguire questa regola, anche se sarebbe la cosa migliore.

Una funzione separata non è solo semplice da testare e debuggare -- la sua stessa esistenza è un commento!
Una funzione separata non è solo semplice da testare e correggere -- la sua stessa esistenza è un commento!

Ad esempio, osserviamo le due funzioni `showPrimes(n)` sotto . Entrambe ritornano i [numeri primi](https://en.wikipedia.org/wiki/Prime_number) fino a `n`.

Expand Down
2 changes: 1 addition & 1 deletion 1-js/03-code-quality/05-testing-mocha/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ Il `describe` annidato definisce un nuovo "sotto-gruppo" di test. Nell'output po

[iframe height=250 src="pow-4" edit border="1"]

In futuro potremmo aggiungere più `it` e `describe` allo stesso livello, ognugo di questi avrà le proprie funzioni di supporto ma non potranno vedere `makeTest`.
In futuro potremmo aggiungere più `it` e `describe` allo stesso livello, ognuno di questi avrà le proprie funzioni di supporto ma non potranno vedere `makeTest`.

````smart header="`before/after` and `beforeEach/afterEach`"
Possiamo impostare le funzione `before/after` (prima/dopo) che vengono eseguite prima/dopo i test, o addirittura le funzioni `beforeEach/afterEach` (prima di ogni/dopo di ogni) che verranno eseguite prima di *ogni* `it`.
Expand Down
2 changes: 1 addition & 1 deletion 1-js/03-code-quality/06-polyfills/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ I moderni 'bundler' utilizzati per 'assemblare' progetti, come [webpack](http://

Nuove caratteristiche di un linguaggio possono riguardare, oltre alla sintassi, operatori e costrutti, anche funzioni integrate.

Ad esempio, `Math.trunc(n)` è una funziona che "tronca" la parte decimale di un numero, es. `Math.trunc(1.23) = 1`.
Ad esempio, `Math.trunc(n)` è una funziona che "tronca" la parte decimale di un numero, es. `Math.trunc(1.23)` ritorna `1`.

In alcuni (vecchissimi) motori JavaScript, non esiste `Math.trunc`, quindi il codice non funzionerebbe.

Expand Down
2 changes: 1 addition & 1 deletion 1-js/04-object-basics/04-object-methods/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ user = {
// la sintassi più breve risulta più carina
user = {
*!*
sayHi() { // equivalente a "sayHi: function()"
sayHi() { // equivalente a "sayHi: function(){...}"
*/!*
alert("Hello");
}
Expand Down
14 changes: 7 additions & 7 deletions 1-js/05-data-types/08-weakmap-weakset/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Ad esempio:
```js
let john = { name: "John" };

// l'oggetto è accessibilie, john è un suo riferimento
// l'oggetto è accessibile, john è un suo riferimento

// sovrascriviamo il riferimento
john = null;
Expand Down Expand Up @@ -99,7 +99,7 @@ Confrontiamolo con l'esempio di `Map` visto sopra. Ora, se `john` esiste solo co
- `weakMap.delete(key)`
- `weakMap.has(key)`

Perché questa limitazione? Per ragioni tecniche. Se un oggetto ha perso tutti i riferimenti (come `john` nel codice sopra), allora verrà automaticamente eliminato. Ma tecnicamente non è specificato esattamente *quando averrà la pulizia*.
Perché questa limitazione? Per ragioni tecniche. Se un oggetto ha perso tutti i riferimenti (come `john` nel codice sopra), allora verrà automaticamente eliminato. Ma tecnicamente non è specificato esattamente *quando avverrà la pulizia*.

Sarà il motore JavaScript a deciderlo. Potrebbe decidere di effettuare subito la pulizia della memoria oppure aspettare più oggetti per eliminarli in blocco. Quindi, tecnicamente il numero degli elementi di una `WeakMap` non è conosciuto. Il motore potrebbe già aver effettuato la pulizia oppure no, o averlo fatto solo parzialmente. Per questo motivo, i metodi che accedono a `WeakMap` per intero non sopo supportati.

Expand All @@ -120,7 +120,7 @@ weakMap.set(john, "secret documents");

Proviamo a guardare un esempio.

Immaginiamo di avere del codice che tiene nota del numero di visite per ogni utente. L'informazioni viene memorizzata in un map: l'utente è la chiave, mentre il conteggio delle visite è il valore. Quando l'utente esce, vogliamo smettere di mantenere in memoria il conteggio delle visite.
Immaginiamo di avere del codice che tiene nota del numero di visite per ogni utente. L'informazione viene memorizzata in un map: l'utente è la chiave, mentre il conteggio delle visite è il valore. Quando l'utente esce, vogliamo smettere di mantenere in memoria il conteggio delle visite.

Qui vediamo un esempio di conteggio utilizzando `Map`:

Expand Down Expand Up @@ -188,7 +188,7 @@ function process(obj) {
}

*!*
// Ora utilizzaimo process() in un altro file:
// Ora utilizziamo process() in un altro file:
*/!*

// 📁 main.js
Expand All @@ -205,7 +205,7 @@ obj = null;
alert(cache.size); // 1 (Ouch! L'oggetto è ancora in cache, sta occupando memoria!)
```

Per chiamate multiple di `process(obj)` con lo stesso oggetto, il risultato viene calcolato solamente la prima volta, le successive chiamate lo prenderanno dalla `cache`. Il lato negatico è che dobbiamo ricordarci di pulire la `cache` quando non è più necessaria.
Per chiamate multiple di `process(obj)` con lo stesso oggetto, il risultato viene calcolato solamente la prima volta, le successive chiamate lo prenderanno dalla `cache`. Il lato negativo è che dobbiamo ricordarci di pulire la `cache` quando non è più necessaria.

Se sostituiamo `Map` con `WeakMap`, il problema si risolve. I risultati in cache vengono automaticamente rimossi una volta che l'oggetto viene ripulito dal garbage collector.

Expand All @@ -232,10 +232,10 @@ let obj = {/* un oggetto */};
let result1 = process(obj);
let result2 = process(obj);

// ...più tadi, quando non abbiamo più bisogno dell'oggetto
// ...più tardi, quando non abbiamo più bisogno dell'oggetto
obj = null;

// Non possiamo ottenere la dimensione della cache, poichè è una WeakMap,
// Non possiamo ottenere la dimensione della cache, poiché è una WeakMap,
// ma è 0 oppure lo sarà presto
// Quando un oggetto viene ripulito dal garbage collector, anche i dati associati vengono ripuliti
```
Expand Down
2 changes: 1 addition & 1 deletion 1-js/05-data-types/09-keys-values-entries/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,5 @@ let doublePrices = Object.fromEntries(
alert(doublePrices.meat); // 8
```

Ad un primo sguardo potrebbe risultare complesso, ma diventa molto più familiare dopo un paio di utilizzi.
Ad un primo sguardo potrebbe risultare complesso, ma diventa molto più familiare dopo un paio di utilizzi. In questo modo possono essere create potenti catene per la trasformazione.

20 changes: 9 additions & 11 deletions 1-js/11-async/02-promise-basics/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,19 @@ La funzione passata a `new Promise` è chiamata *esecutore (executor)*. Quando l

I suoi argomenti `resolve` e `reject` sono delle callback fornite da JavaScript stesso. Il nostro codice sta solamente dentro l'esecutore.

![](promise-resolve-reject.svg)
- `resolve(value)` — se il processo termina correttamente, col risultato `value`.
- `reject(error)` — se si verifica un errore, `error` è l'oggetto errore.

Ricapitolando: l'esecutore parte automaticamente e tenta di eseguire un compito. Quando l'esecuzione termina, viene invocato `resolve` in caso di successo, oppure `reject` in caso di errore.

L'oggetto `promise` risultante ha queste proprietà interne:
L'oggetto `promise` restituito ha le seguenti proprietà interne:

- `state` — inizialmente "pending", poi cambia con "fulfilled" o "rejected",
- `result` — un valore arbitrario di tua scelta, inizialmente `undefined`.
- `state` — inizialmente "pending", poi cambia in "fulfilled" se viene invocato `resolve` o in "rejected" se viene invocato `reject`.
- `result` — inizialmente `undefined`, poi cambia in `value` se viene invocato `resolve(value)` o in `error` se viene invocato `reject(error)`.

Quando l'esecutore finisce il lavoro (job), dovrebbe chiamare una delle funzioni che riceve come argomento:
Quindi l'esecutore, alla fine, mette la promise in uno di questi stati:

- `resolve(value)` — per indicare che il lavoro è finito con successo:
- imposta `state` come `"fulfilled"`,
- imposta `result` come `value`.
- `reject(error)` — per indicare che si è verificato un errore:
- imposta `state` come `"rejected"`,
- imposta `result` come `error`.
![](promise-resolve-reject.svg)

Più avanti vedremo come questi cambiamenti diventano noti ai "fan".

Expand Down
4 changes: 2 additions & 2 deletions 1-js/11-async/07-microtask-queue/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Come detto nella [specifica](https://tc39.github.io/ecma262/#sec-jobs-and-job-qu
- La coda è primo-dentro-primo-fuori: i task messi in coda per primi sono eseguiti per primi.
- L'esecuzione di un task è iniziata solo quando nient'altro è in esecuzione.

Oppure, per dirla in modo semplice, quando una promise è pronta, i suoi gestori `.then/catch/finally` sono messi nella coda. Non sono ancora eseguiti. Il motore JavaScript prende un task dalla coda e lo esegue, quando diventa libero dal codice corrente.
Oppure, per dirla in modo semplice, quando una promise è pronta, i suoi gestori `.then/catch/finally` sono messi nella coda. Non vengono ancora eseguiti. Il motore JavaScript prende un task dalla coda e lo esegue, quando diventa libero dal codice corrente.

Questo è il motivo per cui "codice finito" nell'esempio sopra viene mostrato prima.

Expand All @@ -40,7 +40,7 @@ I gestori delle promise passano sempre da quella coda interna.

Se c'è una catena con diversi `.then/catch/finally`, allora ognuno di essi viene eseguito in modo asincrono. Cioè, viene prima messo in coda ed eseguito quando il codice corrente è completo e i gestori messi in coda precedentemente sono finiti.

**Che cosa succede se per noi l'ordine è importante? Come possiamo far funzionare `codice finito` dopo `promise completa`?**
**Che cosa succede se per noi l'ordine è importante? Come possiamo far funzionare `code finished` dopo `promise done`?**

Facile, basta metterlo in coda con `.then`:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@ Un esempio di utilizzo (visualizza gli autori delle commit nella console):
}
}
})();

// Note: If you are running this in an external sandbox, you'll need to paste here the function fetchCommits described above
```

Questo è esattamente quello che volevamo. I meccanismi interni delle richieste paginate sono invisibili dall'esterno. Per noi non è altro che un generatore asincrono che ritorna delle commit.
Expand Down
6 changes: 6 additions & 0 deletions 2-ui/1-document/10-size-and-scroll-window/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ alert('Scorrimento corrente da sinistra: ' + window.pageXOffset);

Queste proprietà sono in sola lettura.

```smart header="`scrollX` e `scrollY` disponibili anche come proprietà di `window`"
Per ragioni storiche, esistono entrambe le proprietà, ma sono identiche:
- `window.pageXOffset` è un alias di `window.scrollX`.
- `window.pageYOffset` è un alias di `window.scrollY`.
```

## Lo scorrimento con scrollTo, scrollBy, scrollIntoView [#window-scroll]

```warn
Expand Down
6 changes: 3 additions & 3 deletions 4-binary/03-blob/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ link.href = URL.createObjectURL(blob);

We can also create a link dynamically in JavaScript and simulate a click by `link.click()`, then download starts automatically.

Here's the similar code that causes user to download the dynamicallly created `Blob`, without any HTML:
Here's the similar code that causes user to download the dynamically created `Blob`, without any HTML:

```js run
let link = document.createElement('a');
Expand Down Expand Up @@ -186,7 +186,7 @@ let context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
// we can context.rotate(), and do many other things on canvas

// toBlob is async opereation, callback is called when done
// toBlob is async operation, callback is called when done
canvas.toBlob(function(blob) {
// blob ready, download it
let link = document.createElement('a');
Expand Down Expand Up @@ -235,7 +235,7 @@ That makes Blobs convenient for upload/download operations, that are so common i

Methods that perform web-requests, such as [XMLHttpRequest](info:xmlhttprequest), [fetch](info:fetch) and so on, can work with `Blob` natively, as well as with other binary types.

We can easily convert betweeen `Blob` and low-level binary data types:
We can easily convert between `Blob` and low-level binary data types:

- We can make a Blob from a typed array using `new Blob(...)` constructor.
- We can get back `ArrayBuffer` from a Blob using `FileReader`, and then create a view over it for low-level binary processing.
2 changes: 1 addition & 1 deletion 5-network/11-websocket/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Sec-WebSocket-Version: 13
- `Origin` -- l'origine della pagina del client, ad esempio: `https://javascript.info`. Gli oggetti WebSocket sono per loro natura cross-origin. Non vi sono headers particolari o altre limitazioni. I server di vecchia data non gestiscono i WebSocket in nessun modo, quindi non ci sono problemi di compatibilità. Ma l'header `Origin` è importante, dal momento che permette al server di decidere se parlare o meno con quel sito.
- `Connection: Upgrade` -- indica che il client vuole cambiare protocollo di comunicazione.
- `Upgrade: websocket` -- il protocollo richiesto è "websocket".
- `Sec-WebSocket-Key` -- una chiave generata randomicamente dal browser per sicurezza.
- `Sec-WebSocket-Key` -- una chiave casuale generata dal browser per sicurezza.
- `Sec-WebSocket-Version` -- versione di protocollo del WebSocket, 13 è quella corrente.

```smart header="L'handsnake del WebSocket non può essere emulato."
Expand Down
18 changes: 9 additions & 9 deletions 6-data-storage/03-indexeddb/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ openRequest.onupgradeneeded = function(event) {
};
```

Please note: as our current version is `2`, `onupgradeneeded` handler has a code branch for version `0`, suitable for users that are accessing for the first time and have no database, and also for version `1`, for upgrades.
Please note: as our current version is `2`, the `onupgradeneeded` handler has a code branch for version `0`, suitable for users that are accessing for the first time and have no database, and also for version `1`, for upgrades.

And then, only if `onupgradeneeded` handler finishes without errors, `openRequest.onsuccess` triggers, and the database is considered successfully opened.

Expand Down Expand Up @@ -156,7 +156,7 @@ openRequest.onsuccess = function() {
openRequest.onblocked = function() {
// this event shouldn't trigger if we handle onversionchange correctly

// it means that there's another open connection to same database
// it means that there's another open connection to the same database
// and it wasn't closed after db.onversionchange triggered for it
};
*/!*
Expand All @@ -171,7 +171,7 @@ We can handle things more gracefully in `db.onversionchange`, prompt the visitor

Or, an alternative approach would be to not close the database in `db.onversionchange`, but instead use the `onblocked` handler (in the new tab) to alert the visitor, tell him that the newer version can't be loaded until they close other tabs.

These update collisions happen rarely, but we should at least have some handling for them, at least `onblocked` handler, to prevent our script from dying silently.
These update collisions happen rarely, but we should at least have some handling for them, at least an `onblocked` handler, to prevent our script from dying silently.

## Object store

Expand All @@ -189,7 +189,7 @@ An example of an object that can't be stored: an object with circular references

**There must be a unique `key` for every value in the store.**

A key must be one of the these types - number, date, string, binary, or array. It's a unique identifier, so we can search/remove/update values by the key.
A key must be one of these types - number, date, string, binary, or array. It's a unique identifier, so we can search/remove/update values by the key.

![](indexeddb-structure.svg)

Expand Down Expand Up @@ -253,7 +253,7 @@ db.deleteObjectStore('books')

The term "transaction" is generic, used in many kinds of databases.

A transaction is a group operations, that should either all succeed or all fail.
A transaction is a group of operations, that should either all succeed or all fail.

For instance, when a person buys something, we need to:
1. Subtract the money from their account.
Expand Down Expand Up @@ -347,9 +347,9 @@ Usually, we can assume that a transaction commits when all its requests are comp

So, in the example above no special call is needed to finish the transaction.

Transactions auto-commit principle has an important side effect. We can't insert an async operation like `fetch`, `setTimeout` in the middle of transaction. IndexedDB will not keep the transaction waiting till these are done.
Transactions auto-commit principle has an important side effect. We can't insert an async operation like `fetch`, `setTimeout` in the middle of a transaction. IndexedDB will not keep the transaction waiting till these are done.

In the code below, `request2` in line `(*)` fails, because the transaction is already committed, and can't make any request in it:
In the code below, `request2` in the line `(*)` fails, because the transaction is already committed, and can't make any request in it:

```js
let request1 = books.add(book);
Expand All @@ -370,7 +370,7 @@ That's because `fetch` is an asynchronous operation, a macrotask. Transactions a

Authors of IndexedDB spec believe that transactions should be short-lived. Mostly for performance reasons.

Notably, `readwrite` transactions "lock" the stores for writing. So if one part of application initiated `readwrite` on `books` object store, then another part that wants to do the same has to wait: the new transaction "hangs" till the first one is done. That can lead to strange delays if transactions take a long time.
Notably, `readwrite` transactions "lock" the stores for writing. So if one part of the application initiated `readwrite` on `books` object store, then another part that wants to do the same has to wait: the new transaction "hangs" till the first one is done. That can lead to strange delays if transactions take a long time.

So, what to do?

Expand Down Expand Up @@ -792,7 +792,7 @@ await inventory.add({ id: 'js', price: 10, created: new Date() }); // Error

The next `inventory.add` after `fetch` `(*)` fails with an "inactive transaction" error, because the transaction is already committed and closed at that time.

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

Expand Down
Loading