W3docs

JavaScript IndexedDB

Impara JavaScript IndexedDB: apri un database, gestisci onupgradeneeded, crea object store e indici, esegui transazioni, aggiungi, ottieni, aggiorna ed elimina record con i cursori.

IndexedDB è una potente API di archiviazione lato client, più robusta delle altre soluzioni di storage locale disponibili nei browser web. Consente alle applicazioni web di memorizzare e manipolare quantità significative di dati strutturati in modo asincrono. IndexedDB è ideale per applicazioni che richiedono archiviazione dati offline, elevate prestazioni e ricche capacità di interrogazione senza dipendere da una connessione di rete.

Questo capitolo copre tutto il necessario per iniziare a usare IndexedDB: aprire un database e gestire gli aggiornamenti di versione, creare object store e indici, eseguire transazioni ed effettuare il ciclo CRUD completo (add, get, put, delete), inclusa l'iterazione con i cursori e le interrogazioni tramite indici.

Quando usare IndexedDB

IndexedDB può memorizzare quasi qualsiasi valore JavaScript — object, array, date, blob e file — non solo string, e può contenere centinaia di megabyte, ben oltre il limite di ~5 MB di localStorage e sessionStorage. È un archivio NoSQL transazionale chiave/valore con indici, il che lo rende la scelta giusta per:

  • App offline-first che devono funzionare senza connessione di rete.
  • Caching di grandi dataset come risposte API, documenti o file multimediali.
  • Interrogare i record per campi indicizzati anziché caricare tutto in memoria.

Se hai bisogno di memorizzare solo pochi valori stringa di piccole dimensioni, opta per le più semplici Web Storage API. Consulta il capitolo Storage API per una panoramica su come il browser gestisce le quote di archiviazione tra questi meccanismi.

L'API asincrona basata sugli eventi

Ogni operazione IndexedDB è asincrona e basata sugli eventi. Chiamate come indexedDB.open() o store.get() restituiscono immediatamente un oggetto request; il risultato effettivo arriva in seguito tramite i gestori di eventi onsuccess / onerror. Il tuo codice non si blocca mai in attesa di I/O su disco. Per questo motivo, non puoi leggere un risultato in modo sincrono subito dopo aver emesso una richiesta — devi aspettare che l'evento venga scatenato. (Il codice moderno spesso racchiude queste richieste in Promise, ma la API nativa è basata su callback, come mostrano gli esempi seguenti.)

Configurare un database IndexedDB

Passo 1: Aprire un database

Per usare IndexedDB, il primo passo è aprire un database con indexedDB.open(name, version). Il secondo argomento opzionale è un numero di versione intero. Se il database non esiste, o la versione richiesta è superiore a quella memorizzata, viene scatenato l'evento onupgradeneeded — questo è l'unico posto in cui è consentito modificare la struttura del database (creare o eliminare object store e indici).

La chiamata restituisce una richiesta e può scatenare tre eventi:

  • onsuccess — il database è stato aperto ed è pronto all'uso (event.target.result è l'IDBDatabase).
  • onerror — l'apertura è fallita.
  • onupgradeneeded — è necessaria una modifica allo schema (vedi Passo 2).

Ecco come puoi creare o aprire un database IndexedDB. Dopo un'operazione riuscita, chiudiamo il database per evitare effetti indesiderati negli altri esempi. Puoi saltare questo passaggio nel tuo codice o includerlo se necessario.

Attenzione: Chiamare deleteDatabase() eliminerà tutti i dati di questo database. Questo è solo a scopo di test e non dovrebbe essere utilizzato in produzione.


javascript— editable

Passo 2: Creare Object Store

Una volta aperto il database, puoi procedere a creare un object store, analogo a una tabella nei database relazionali. Nota che questo può essere fatto solo durante un aggiornamento di versione (quando si apre il database con un numero di versione più alto). L'evento da ascoltare è onupgradeneeded.

Quando crei uno store, scegli come definire la chiave primaria di ogni record:

  • { keyPath: 'id' } — la chiave viene letta dalla proprietà id di ogni object memorizzato (chiave in-line).
  • { keyPath: 'id', autoIncrement: true } — lo store genera automaticamente una chiave sequenziale se non ne fornisci una.
  • { autoIncrement: true } — le chiavi vengono generate e memorizzate separatamente dal valore (chiave out-of-line).

Puoi anche creare indici all'interno di onupgradeneeded. Un indice ti consente di cercare record tramite una proprietà diversa dalla chiave primaria. Passa { unique: true } per rifiutare valori duplicati per quella proprietà.


javascript— editable

Transazioni

Una volta configurati il database e gli object store, dovrai gestire le operazioni sui dati tramite le transazioni. Una transazione in IndexedDB è un meccanismo che raggruppa più operazioni in una singola unità di lavoro che ha successo completamente o fallisce completamente. È essenziale per garantire la coerenza e l'integrità dei dati, specialmente quando più operazioni dipendono l'una dall'altra per produrre un risultato corretto.

Come usare le transazioni in IndexedDB

Passo 1: Avviare una transazione

Per eseguire qualsiasi operazione in IndexedDB, si inizia creando una transazione su un database. Una transazione viene creata specificando quali object store coinvolgerà e la modalità della transazione, che può essere "readonly" o "readwrite".

Passo 2: Accedere a un Object Store

All'interno di una transazione, puoi accedere a uno o più object store per eseguire operazioni sui dati.

Passo 3: Eseguire le operazioni

Una volta che hai accesso a un object store, puoi eseguire varie operazioni come aggiungere, recuperare, aggiornare o eliminare dati. Ogni operazione restituisce un oggetto request che puoi usare per gestire gli eventi di successo o errore.

Passo 4: Completare la transazione

Una transazione si completa automaticamente una volta che tutte le operazioni emesse al suo interno sono state risolte, con successo o con un fallimento. Puoi anche ascoltare l'evento complete sulla transazione per eseguire azioni dopo che tutte le operazioni sono state completate con successo.

Ecco un esempio di transazione completa:


javascript— editable

Lettura dei dati

Per recuperare i dati, usa store.get(key) o un cursore per iterare su più record. Ecco alcuni esempi rapidi:

Recupero di un singolo record:


javascript— editable

Iterazione con un cursore:


javascript— editable

Interrogare con gli indici

La chiave primaria ti consente di recuperare un record quando ne conosci già la chiave. Un indice ti consente di cercare per un'altra proprietà — ad esempio, trovare un libro tramite il suo title. Accedi a un indice con store.index(name), quindi chiama get(), getAll() o openCursor() su di esso proprio come su uno store.

Ricerca di un record tramite una proprietà indicizzata:


javascript— editable

Puoi anche limitare una query a un intervallo di chiavi con IDBKeyRange (ad esempio IDBKeyRange.bound('A', 'M') per recuperare tutti i libri il cui titolo inizia tra A e M), passando l'intervallo a getAll() o openCursor().

Aggiornamento ed eliminazione dei record

Per modificare i dati esistenti, usa store.put() con la stessa chiave. Per rimuovere dati, usa store.delete(key).

Aggiornamento di un record:


javascript— editable

Eliminazione di un record:


javascript— editable

Come visualizzare il contenuto di IndexedDB nel browser

Dopo aver memorizzato e manipolato i dati, potresti voler ispezionare ciò che è effettivamente salvato nel tuo browser. La maggior parte dei browser moderni mostra ciò che è memorizzato in IndexedDB. Di seguito è riportato un esempio dagli strumenti per sviluppatori di Chrome:

IndexedDB

Best practice per l'uso delle transazioni

Per garantire che la tua implementazione di IndexedDB rimanga affidabile e performante, segui queste linee guida:

  1. Minimizza l'ambito: Mantieni le transazioni il più piccole possibile, sia in termini di numero di operazioni che di durata. Questo riduce la probabilità di conflitti e migliora le prestazioni.
  2. Gestione degli errori: Implementa sempre la gestione degli errori sia a livello di richiesta che di transazione. Questo aiuta a diagnosticare i problemi e a prevenire aggiornamenti parziali che potrebbero causare corruzione dei dati.
  3. Concorrenza: Tieni presente che, sebbene IndexedDB sia asincrono e non bloccante, le transazioni sullo stesso database vengono messe in coda ed eseguite in serie per prevenire race condition e inconsistenze.

Conclusione

IndexedDB fornisce una piattaforma robusta per la gestione di dati complessi nelle applicazioni web, rendendolo uno strumento essenziale per gli sviluppatori web moderni. Attraverso una corretta implementazione delle sue funzionalità, gli sviluppatori possono memorizzare, recuperare, aggiornare ed eliminare in modo efficiente i dati lato client, migliorando le prestazioni dell'applicazione e l'esperienza utente.

Per esigenze di archiviazione più semplici e per comprendere il quadro più ampio dello storage nel browser, consulta questi capitoli correlati:

  • localStorage e sessionStorage — archiviazione chiave/valore leggera per piccole quantità di dati stringa.
  • The Storage API — come il browser gestisce le quote di archiviazione e la persistenza tra i meccanismi.
  • Lavorare con JSON — serializzazione dei dati, utile quando si spostano object da e verso lo storage.

Pratica

Pratica
Quali sono le caratteristiche di IndexedDB in JavaScript?
Quali sono le caratteristiche di IndexedDB in JavaScript?
Was this page helpful?