IndexedDB con ExtJS

Luca Minuti - May 6 - - Dev Community

La possibilità di salvare informazioni localmente sul browser è una funzionalita molto utile che si è evoluta nel tempo. Ovviamente sul browser, per motivi di sicurezza, non è possibile scrivere e leggere a piacimento sul file system dell'utente. Ma tramite diversi meccanismi è comunque possibile memorizzare delle informazioni in maniera persistente.

In questo articolo vedremo diversi tipi di storage e come utilizzarli con ExtJS. In particolare analizzeremo l'implementazione di IndexedDB offerta dalla libreria (N)ext.

Cookie

Il modo "classico" di salvare dati sul browser è tramite i cookie che permettono proprio di salvare piccole stringhe da recuperare in un secondo tempo dal server oppure direttamente sul browser tramite codice JavaScript. Più recentemente sono strati introdotti dei veri e propri database: LocalStorage, SessionStorage e IndexexDB.

Cookie

LocalStorage e SessioneStorage

localStorage e SessionStorage sono due semplici database chiave/valore presenti nel browser. In pratica per ogni "origin" (host+porta) è possibile associare una serie chiavi a dei valori in modo da poterli recuperare in un secondo tempo.

LocalStorage

La differenza tra i due è che mentre il LocalStorage è permanente, i dati contenuti nel SessionStorage vengono eliminati alla chiusura del browser.

Limitazioni

I problemi principali di questi tipi di storage sono i seguenti:

  • Le dimensioni: ci sono differenze tra i vari browser ma in generale non è possibile salvare più di 5MB di dati
  • L'API è sincrona, quindi se la dimensione dei dati è consistente o si eseguono molte operazioni di lettura/scrittura si rischia di "freezare" il browser.
  • Gli elementi vengono salvati come stringa (eventualmente chiamando il metodo toString()), di conseguenza per gli oggetti più complessi è necessario eseguire una conversione manualmente.

ExtJS

In ExtJS ci sono varie classi che fanno uso di questi tipi di storage:

  • Ext.util.LocalStorage: Questa classe è un semplice wrapper della classe localStorage nativa del browser. Semplicemente si limita a salvare i dati localmente nel caso in cui il browser non supporti localStorage.
  • Ext.state.LocalStorage: Questa classe serve a salvare lo stato dei componenti (dimensione, posizione, ecc.) in modo da ripresentarli ad una successiva apertura dell'applicazione (vedi Ext.Stateful).
  • Ext.data.proxy.LocalStorage: Questo proxy, collegato ad uno store, permette di leggere e scrivere dati dal localStorage.
  • Ext.data.proxy.SessionStorage: Esattamente come il precedente ma legge e scrive sul SessionStorage.

IndexedDB

Per ovviare ai problemi di LocalStorage da qualche tempo su tutti i principali browser desktop e mobili (vedi browser supportati) è possibile usare IndexedDB. A differenza di LocalStorage consente alle applicazioni web di memorizzare grandi quantità di dati strutturati, offrendo un'interfaccia di accesso flessibile e basata sulle Promise.

funzionalità principali

  • Modello di dati: IndexedDB supporta la memorizzazione di oggetti JavaScript complessi, consentendo la memorizzazione di dati strutturati in modo gerarchico.
  • Dimensione dei dati: IndexedDB gestisce grandi quantità di dati in modo più efficiente rispetto a localStorage.
  • Interfaccia di accesso: IndexedDB fornisce un'interfaccia di programmazione più complessa rispetto a localStorage. Richiede la comprensione di concetti come transazioni, cursori e indici per manipolare i dati in modo efficiente.
  • Supporto per transazioni: IndexedDB supporta le transazioni, consentendo operazioni atomiche su più record di dati.
  • Performance: IndexedDB è progettato per gestire grandi quantità di dati in modo efficiente, offrendo prestazioni migliori rispetto a localStorage.

Il difetto principale di IndexedDB è proprio la complessità dell'API. In JavaScript esistono diverse librerie che cercano di semplificarne l'uso, per esempio:

In particolare IDB-Keyval offre un'API estremamente semplificata che ricorda molto quella di LocalStorage. Questa semplificazione chiaramente ha delle conseguenze e infatti alcune caratteristiche avanzate di IndexedDB (come l'uso delle transazioni) vengono meno. Ma per chi viene da LocalStorage e ha bisogno semplicemente di più performance e spazio di archiviazione sicuramente è una scelta interessante.

ExtJS - (N)ext

Purtroppo in ExtJS non c'è nessun supporto nativo per IndexedDB. Ed è per questo che ho deciso di aggiungerlo nella libreria (N)ext che ho recentemente pubblicato su GitHub.

Con (N)ext è possibile connettersi ad un database in questo modo:

// If you add a new store in the schema you must increment the database version!
database = await Next.IndexedDB.open('dbname', {
    version: 1,
    stores: ['store1','store2', 'store3', 'store4']
});
Enter fullscreen mode Exit fullscreen mode

Se il database non esiste verrà creato con i 4 store (che non hanno niente a che fare con gli store di ExtJS), che si possono considerare come delle tabelle. Per come funziona IndexedDB è importante ricordarsi che qualora serva uno store addizionale è necessario incrementare il numero di versione.

È importante notare che l'apertura del database (come praticamente tutte le altre API) è asincrona. Infatti nell'esempio viene chiamata usando await.

IndexedDB

Una volta ottenuto un riferimento al database è possibile interagire con gli store. La libreria offre diverse possibilità, di seguito sono elencate le principali.

Inserimento/modifica di un elemento sullo store

await database.store1.set(5, {
    name: 'Charlie'
});
Enter fullscreen mode Exit fullscreen mode

Come si può vedere dall'esempio il valore è un oggetto e, in questo caso, non c'è bisogno di nessuna trasformazione.

Lettura di un valore

const value = await database.store1.get(5);
Enter fullscreen mode Exit fullscreen mode

Anche in questo caso la variabile value viene valorizzata direttamente con l'oggetto.

Lettura di tutte le chiavi

const keys = await database.store1.keys();
Enter fullscreen mode Exit fullscreen mode

Questo metodo restituisce in array con tutte le chiavi dello store.

Lettura di tutti i valori

const values = await database.store1.values();
Enter fullscreen mode Exit fullscreen mode

Questo metodo restituisce in array con tutti i valori dello store.

Eliminazione di un valore

await database.store1.del(5);
Enter fullscreen mode Exit fullscreen mode

Il metodo del elimina l'elemento indicato dalla chiave.

Eliminazione di tutto lo store

await database.store1.clear();
Enter fullscreen mode Exit fullscreen mode

Questo metodo svuota l'intero store.

Conclusioni

In questo articolo abbiamo visto i principali metodi per salvare informazioni persistenti sul browser in particolare con IndexedDB. Ci siamo poi soffermati ad analizzare quanto offerto dalla libreria GitHub.

Vi invito a provarla e farmi sapere le vostre impressioni!

. . . . . . . . . . . .