Funzionando con IndexedDB

Uno degli sviluppi più interessanti negli standard Web ultimamente è la specifica del Database indicizzato (IndexedDB in breve). Per un momento divertente puoi leggere le specifiche te stesso. In questo tutorial spiegherò questa funzione e, spero, ti fornirò qualche spunto per utilizzare questa potente funzionalità tu stesso.


Panoramica

Come una specifica, IndexedDB è attualmente una raccomandazione del candidato.

In poche parole, IndexedDB offre un modo per memorizzare grandi quantità di dati sul browser dell'utente. Qualsiasi applicazione che ha bisogno di inviare molti dati attraverso il cavo potrebbe trarre grandi vantaggi dall'essere in grado di archiviare tali dati sul client. Ovviamente lo storage è solo una parte dell'equazione. IndexedDB fornisce anche una potente API di ricerca basata su indici per recuperare i dati necessari.

Potresti chiederti come IndexedDB si differenzia da altri meccanismi di archiviazione?

I cookie sono estremamente ben supportati, ma hanno implicazioni legali e spazio di archiviazione limitato. Inoltre, vengono inviati avanti e indietro sul server ad ogni richiesta, annullando completamente i vantaggi dell'archiviazione lato client.

Anche Local Storage è molto ben supportato, ma limitato in termini di quantità totale di spazio di archiviazione che è possibile utilizzare. L'archiviazione locale non fornisce una vera API di "ricerca" poiché i dati vengono recuperati solo tramite valori chiave. L'archiviazione locale è ideale per le cose "specifiche" che potresti voler memorizzare, ad esempio le preferenze, mentre IndexedDB è più adatto per i dati Ad Hoc (molto simile a un database).

Prima di andare avanti, parliamo onestamente dello stato di IndexedDB in termini di supporto del browser. Come una specifica, IndexedDB è attualmente una raccomandazione del candidato. A questo punto la gente dietro le specifiche è soddisfatta ma ora sta cercando feedback dalla comunità degli sviluppatori. Le specifiche possono cambiare tra ora e la fase finale, raccomandazione W3C. In generale, i browser che supportano IndexedDB ora fanno tutti in modo abbastanza coerente, ma gli sviluppatori dovrebbero essere pronti ad affrontare i prefissi e prendere nota degli aggiornamenti in futuro.

Per quanto riguarda i browser che supportano IndexedDB, hai un po 'di dilemma. Il supporto è davvero buono per il desktop, ma praticamente inesistente per i dispositivi mobili. Vediamo cosa eccellente sito CanIUse.com dice:


Chrome per Android supporta la funzionalità, ma pochissime persone stanno attualmente utilizzando quel browser su dispositivi Android. La mancanza di supporto mobile implica che non dovresti usarlo? Ovviamente no! Speriamo che tutti i nostri lettori abbiano familiarità con il concetto di miglioramento progressivo. Funzionalità come IndexedDB possono essere aggiunte alla tua applicazione in modo tale da non infrangere i browser non supportati. È possibile utilizzare le librerie wrapper per passare a WebSQL su dispositivi mobili o semplicemente saltare la memorizzazione dei dati localmente sui client mobili. Personalmente ritengo che la capacità di memorizzare grandi quantità di dati sul client sia abbastanza importante da poter essere utilizzata anche senza il supporto mobile.


Iniziamo

Abbiamo coperto le specifiche e il supporto, ora diamo un'occhiata all'utilizzo della funzione. La prima cosa che dovremmo fare è controllare il supporto IndexedDB. Mentre ci sono strumenti là fuori che forniscono metodi generici per verificare le funzionalità del browser, possiamo renderlo molto più semplice dal momento che stiamo solo controllando una cosa particolare.

document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" nella finestra) console.log ("SÌ !!! POSSO FARLO !!! WOOT !!!"); else console.log ("I have a sad.");, False);

Lo snippet di codice sopra (disponibile in Test1.html se si scarica il file zip allegato a questo articolo) utilizza il DOMContentLoaded evento per attendere il caricamento della pagina. (Ok, questo è ovvio, ma riconosco che potrebbe non essere familiare a chi ha usato solo jQuery.) Poi vedo semplicemente se indexedDB esiste nel finestra oggetto e se è così, siamo a posto. Questo è l'esempio più semplice, ma in genere vorremmo probabilmente archiviarlo così sapremo in seguito se possiamo usare la funzione. Ecco un esempio leggermente più avanzato (Test2.html).

var idbSupported = false; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" nella finestra) idbSupported = true;, false);

Tutto ciò che ho fatto è stato creato una variabile globale, idbSupported, che può essere usato come flag per vedere se il browser corrente può utilizzare IndexedDB.


Aprire un database

IndexedDB, come puoi immaginare, fa uso di database. Per essere chiari, questa non è un'implementazione di SQL Server. Questo database è locale per il browser e disponibile solo per l'utente. I database IndexedDB seguono le stesse regole dei cookie e dell'archiviazione locale. Un database è unico per il dominio dal quale è stato caricato. Ad esempio, un database chiamato "Foo" creato su foo.com non entrerà in conflitto con un database con lo stesso nome su goo.com. Non solo non entrerà in conflitto, non sarà disponibile anche per altri domini. È possibile memorizzare i dati per il proprio sito Web sapendo che un altro sito Web non sarà in grado di accedervi.

L'apertura di un database avviene tramite il comando open. Nell'uso di base fornisci un nome e una versione. La versione è molto importante per ragioni che coprirò più tardi. Ecco un semplice esempio:

var openRequest = indexedDB.open ("test", 1);

L'apertura di un database è un'operazione asincrona. Per gestire il risultato di questa operazione è necessario aggiungere alcuni listener di eventi. Esistono quattro diversi tipi di eventi che possono essere attivati:

  • successo
  • errore
  • upgradeneeded
  • bloccato

Probabilmente puoi indovinare quale successo e errore implicano. L'evento aggiornato viene utilizzato sia quando l'utente apre per la prima volta il database sia quando si modifica la versione. Bloccato non è qualcosa che accadrà di solito, ma può sparare se una precedente connessione non è mai stata chiusa.

In genere, ciò che dovrebbe accadere è che al primo hit sul tuo sito verrà attivato l'evento aggiornato. Dopo di ciò, solo il gestore del successo. Diamo un'occhiata ad un semplice esempio (test3.html).

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" nella finestra) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test", 1); openRequest.onupgradeneeded = function (e) console.log ("Aggiornamento ..."); openRequest.onsuccess = function (e) console.log ("Success!"); db = e.target.result; openRequest.onerror = function (e ) console.log ("Errore"); console.dir (e);, falso);

Ancora una volta controlliamo se IndexedDB è effettivamente supportato, e se lo è, apriamo un database. Abbiamo coperto tre eventi qui: l'evento necessario per l'aggiornamento, l'evento di successo e l'evento di errore. Per ora concentrati sull'evento di successo. L'evento viene passato tramite un gestore target.result. Lo abbiamo copiato su una variabile globale chiamata db. Questo è qualcosa che useremo in seguito per aggiungere effettivamente i dati. Se lo esegui nel tuo browser (in uno che supporta IndexedDB, ovviamente!), Dovresti vedere il messaggio di upgrade e di successo nella tua console la prima volta che esegui lo script. Il secondo, e così via, le volte che esegui lo script dovresti solo vedere il messaggio di successo.


Negozi di oggetti

Finora abbiamo controllato il supporto IndexedDB, l'abbiamo confermato e aperto una connessione a un database. Ora abbiamo bisogno di un posto dove archiviare i dati. IndexedDB ha un concetto di "Oggetti Stores". Puoi pensare a questo come una tipica tabella di database. (È molto più loose di una tipica tabella di database, ma non preoccupatevi di questo ora.) Gli archivi degli oggetti hanno dati (ovviamente) ma anche un keypath e un set opzionale di indici. I Keypath sono identificatori fondamentalmente univoci per i tuoi dati e sono disponibili in diversi formati. Gli indici saranno trattati in un secondo momento quando inizieremo a parlare del recupero dei dati.

Ora per qualcosa di cruciale. Ricorda l'evento aggiornato menzionato prima? È possibile creare archivi di oggetti solo durante un evento aggiornato. Ora, per impostazione predefinita, verrà eseguito automaticamente la prima volta che un utente raggiunge il tuo sito. Puoi usare questo per creare i tuoi negozi di oggetti. La cosa fondamentale da ricordare è che se mai ne hai bisogno modificare i tuoi negozi di oggetti, dovrai aggiornare la versione (di nuovo in quell'evento aperto) e scrivere il codice per gestire le tue modifiche. Diamo un'occhiata a un semplice esempio di questo in azione.

var idbSupported = false; var db; document.addEventListener ("DOMContentLoaded", function () if ("indexedDB" nella finestra) idbSupported = true; if (idbSupported) var openRequest = indexedDB.open ("test_v2", 1); openRequest.onupgradeneeded = function (e) console.log ("in esecuzione onupgradeneeded"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS"); openRequest .onsuccess = function (e) console.log ("Success!"); db = e.target.result; openRequest.onerror = function (e) console.log ("Errore"); console.dir (e );, falso);

Questo esempio (test4.html) si basa sulle voci precedenti quindi mi concentrerò solo sulle novità. Nell'evento aggiornato, ho fatto uso della variabile del database passata (thisDB). Una delle proprietà di questa variabile è un elenco di negozi di oggetti esistenti chiamati objectStoreNames. Per chi è curioso, questo non è un semplice array ma un "DOMStringList". Non chiedermelo, ma ci sei. Possiamo usare il contiene metodo per vedere se esiste il nostro archivio oggetti e, in caso contrario, crearlo. Questa è una delle poche funzioni sincrone in IndexedDB, quindi non dobbiamo ascoltare il risultato.

Per riassumere quindi - questo è ciò che accadrebbe quando un utente visita il tuo sito. La prima volta che sono qui, l'evento potenziato si accende. Il codice controlla se esiste un archivio oggetti, "firstOS". Non lo farà. Pertanto - è stato creato. Quindi viene eseguito il gestore di successo. La seconda volta che visitano il sito, il numero di versione sarà lo stesso quindi l'evento aggiornato non licenziato.

Ora immagina di voler aggiungere un secondo negozio di oggetti. Tutto quello che devi fare è incrementare il numero di versione e in pratica duplicare il blocco di codice contiene / createObjectStore che vedi sopra. La cosa bella è che il tuo codice aggiornato supporterà sia le persone che sono nuove di zecca per il sito sia quelle che hanno già il primo negozio di oggetti. Ecco un esempio di questo (test5.html):

var openRequest = indexedDB.open ("test_v2", 2); openRequest.onupgradeneeded = function (e) console.log ("running onupgradeneeded"); var thisDB = e.target.result; if (! thisDB.objectStoreNames.contains ("firstOS")) thisDB.createObjectStore ("firstOS");  if (! thisDB.objectStoreNames.contains ("secondOS")) thisDB.createObjectStore ("secondOS"); 

Aggiunta di dati

Una volta pronti gli archivi degli oggetti, puoi iniziare ad aggiungere dati. Questo è - forse - uno degli aspetti più interessanti di IndexedDB. A differenza dei database basati su tabelle tradizionali, IndexedDB consente di memorizzare un oggetto così com'è. Ciò significa che puoi prendere un oggetto JavaScript generico e semplicemente memorizzarlo. Fatto. Ovviamente ci sono alcuni avvertimenti qui, ma per la maggior parte, è tutto.

Lavorare con i dati richiede l'utilizzo di una transazione. Le transazioni richiedono due argomenti. Il primo è un array di tabelle con cui lavorerai. Il più delle volte questo sarà un tavolo. Il secondo argomento è il tipo di transazione. Esistono due tipi di transazioni: readonly e readwrite. L'aggiunta di dati sarà un'operazione di readwrite. Iniziamo creando la transazione:

// Supponiamo che db sia una variabile di database aperta in precedenza var transaction = db.transaction (["people"], "readwrite");

Nota che l'archivio oggetti, "persone", è solo uno che abbiamo inventato nell'esempio sopra. La nostra prossima demo completa ne farà uso. Dopo aver ottenuto la transazione, la chiederai per l'archivio degli oggetti con cui hai detto che avresti lavorato con:

var store = transaction.objectStore ("persone");

Ora che hai il negozio puoi aggiungere dati. Questo viene fatto tramite - attendi - Inserisci metodo.

// Definisci una persona var person = nome: nome, email: email, creato: new Date () // Esegui var request = store.add (person, 1);

Ricorda prima abbiamo detto che è possibile memorizzare tutti i dati che si desidera (per la maggior parte). Quindi la mia persona oggetto sopra è completamente arbitraria. Avrei potuto usare firstName e lastName invece del solo nome. Avrei potuto usare una proprietà di genere. Hai un'idea. Il secondo argomento è la chiave utilizzata per identificare in modo univoco i dati. In questo caso l'abbiamo codificato in modo rigido su 1, il che causerà un problema abbastanza rapidamente. Va bene - impareremo come correggerlo.

L'operazione di aggiunta è asincrona, quindi consente di aggiungere due gestori di eventi per il risultato.

request.onerror = function (e) console.log ("Errore", e.target.error.name); // un qualche tipo di gestore degli errori request.onsuccess = function (e) console.log ("Woot! Did it"); 

Abbiamo un onerror gestore per errori e onSuccess per buoni cambiamenti. Abbastanza ovvio, ma vediamo un esempio completo. Puoi trovarlo nel file test6.html.

>
      

L'esempio precedente contiene un piccolo modulo con un pulsante per attivare un evento per archiviare i dati in IndexedDB. Eseguilo nel browser, aggiungi qualcosa ai campi del modulo e fai clic su aggiungi. Se hai gli strumenti di sviluppo del tuo browser aperti, dovresti vedere qualcosa di simile.


Questo è un ottimo momento per segnalare che Chrome ha un eccellente visualizzatore per i dati IndexedDB. Se fai clic sulla scheda Risorse, espandi la sezione IndexedDB, puoi vedere il database creato da questa demo e l'oggetto appena inserito.


Per favore, vai avanti e premi di nuovo il pulsante Aggiungi dati. Dovresti vedere un errore nella console:


Il messaggio di errore dovrebbe essere un indizio. ConstraintError significa che abbiamo appena provato ad aggiungere dati con la stessa chiave di uno già esistente. Se ricordi, abbiamo codificato quella chiave e noi conosceva sarebbe stato un problema. È ora di parlare con le chiavi.


chiavi

Le chiavi sono la versione di chiavi primarie di IndexedDB. I database tradizionali possono avere tabelle senza chiavi, ma ogni archivio oggetti deve avere una chiave. IndexedDB consente un paio di tipi diversi di chiavi.

La prima opzione è semplicemente specificarla da soli, come abbiamo fatto sopra. Potremmo usare la logica per generare chiavi uniche.

La seconda opzione è un keypath, in cui la chiave è basata su una proprietà dei dati stessi. Considera il nostro esempio di persone: potremmo usare un indirizzo email come chiave.

La tua terza opzione, e secondo me, la più semplice, è usare un generatore di chiavi. Funziona molto come una chiave primaria autonumber ed è il metodo più semplice per specificare le chiavi.

Le chiavi vengono definite quando vengono creati gli archivi degli oggetti. Ecco due esempi: uno utilizza un percorso chiave e uno un generatore.

thisDb.createObjectStore ("test", keyPath: "email"); thisDb.createObjectStore ("test2", autoIncrement: true);

Possiamo modificare la demo precedente creando un archivio oggetti con una chiave autoIncrement:

thisDB.createObjectStore ("persone", autoIncrement: true);

Infine, possiamo prendere la chiamata Aggiungi che abbiamo usato prima e rimuovere la chiave codificata:

var request = store.add (person);

Questo è tutto! Ora puoi aggiungere dati tutto il giorno. Puoi trovare questa versione in test7.html.


Dati di lettura

Passiamo ora alla lettura di singoli pezzi di dati (copriremo più tardi set di dati più grandi). Ancora una volta, ciò avverrà in una transazione e sarà asincrono. Ecco un semplice esempio:

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); // x è un valore var ob = objectStore.get (x); ob.onsuccess = function (e) 

Si noti che la transazione è di sola lettura. La chiamata all'API è solo una semplice chiamata get con la chiave passata. Come soluzione rapida, se pensi che l'uso di IndexedDB sia un po 'prolisso, nota che puoi associare anche molte di queste chiamate. Ecco lo stesso codice scritto scritto molto più stretto:

db.transaction (["test"], "readonly"). objectStore ("test"). get (X) .onsuccess = function (e) 

Personalmente continuo a trovare IndexedDB un po 'complesso, quindi preferisco l'approccio' scomposto 'per aiutarmi a tenere traccia di ciò che sta succedendo.

Il risultato del gestore onsuccess di get è l'oggetto precedentemente memorizzato. Una volta che hai quell'oggetto puoi fare quello che vuoi. Nel nostro prossimo demo (test8.html) abbiamo aggiunto un campo modulo semplice per consentire l'immissione di una chiave e stampare il risultato. Ecco un esempio:


Il gestore per il pulsante Ottieni dati è qui sotto:

function getPerson (e) var key = document.querySelector ("# chiave"). valore; if (key === "" || isNaN (key)) return; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("persone"); var request = store.get (Number (key)); request.onsuccess = function (e) var result = e.target.result; console.dir (risultato); if (result) var s = "

Tasto "+ tasto +"

"; per (campo var in result) s + = field +" = "+ result [field] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Nessuna corrispondenza

";

Per la maggior parte, questo dovrebbe essere auto esplicativo. Ottieni il valore dal campo ed esegui una chiamata get sull'archivio oggetti ottenuto da una transazione. Si noti che il codice visualizzato viene semplicemente visualizzato tutti i campi e li butta via. In una vera applicazione si dovrebbe (si spera) sapere cosa contengono i dati e lavorare con campi specifici.


Leggere più dati

Ecco come otterresti un pezzo di dati. Che ne dici di a lotto di dati? IndexedDB ha il supporto per quello che viene chiamato un cursore. Un cursore ti consente di scorrere i dati. È possibile creare cursori con un intervallo opzionale (un filtro di base) e una direzione.

Ad esempio, il seguente blocco di codice apre un cursore per recuperare tutti i dati da un archivio oggetti. Come ogni altra cosa che abbiamo fatto con i dati, questo è asincrono e in una transazione.

var transaction = db.transaction (["test"], "readonly"); var objectStore = transaction.objectStore ("test"); var cursor = objectStore.openCursor (); cursor.onsuccess = function (e) var res = e.target.result; if (res) console.log ("Chiave", res.key); console.dir ("Dati", valore_valore); res.continue (); 

Il gestore di successo viene passato un oggetto risultato (la variabile res sopra). Contiene la chiave, l'oggetto per i dati (nella chiave di valore sopra) e un metodo continua che viene utilizzato per iterare alla successiva parte di dati.

Nella seguente funzione, abbiamo usato un cursore per scorrere tutti i dati del dispositivo di archiviazione. Dal momento che stiamo lavorando con dati di "persona", abbiamo chiamato questo getPeople:

function getPeople (e) var s = ""; db.transaction (["people"], "readonly"). objectStore ("people"). openCursor (). onsuccess = function (e) var cursor = e.target.result; if (cursore) s + = "

Tasto "+ cursor.key +"

"; per (campo var in cursor.value) s + = field +" = "+ cursor.value [field] +"
"; s + ="

"; cursor.continue (); document.querySelector (" # status2 "). innerHTML = s;

Puoi vedere una demo completa di questo nel tuo download come file test9.html. Ha una logica Add Person come negli esempi precedenti, quindi crea semplicemente poche persone e poi premi il pulsante per visualizzare tutti i dati.


Così ora sai come ottenere un pezzo di dati e come ottenere tutti i dati. Passiamo ora al nostro ultimo argomento: lavorare con gli indici.


Chiamano questo IndexedDB, giusto?

Abbiamo parlato di IndexedDB per l'intero articolo, ma non abbiamo ancora fatto alcun - bene - indici. Gli indici sono una parte cruciale degli archivi di oggetti IndexedDB. Forniscono un modo per recuperare i dati in base al loro valore e specificano se un valore deve essere univoco all'interno di un negozio. Più avanti dimostreremo come utilizzare gli indici per ottenere una serie di dati.

Primo: come crei un indice? Come tutto il resto strutturale, devono essere eseguiti in un evento di aggiornamento, fondamentalmente nello stesso momento in cui crei il tuo archivio oggetti. Ecco un esempio:

var objectStore = thisDb.createObjectStore ("persone", autoIncrement: true); // primo arg è il nome dell'indice, il secondo è il percorso (col); objectStore.createIndex ("name", "name", unique: false); objectStore.createIndex ("email", "email", unique: true);

Nella prima riga creiamo il negozio. Prendiamo quel risultato (un oggetto objectStore) ed eseguiamo il createIndex metodo. Il primo argomento è il nome per l'indice e il secondo è la proprietà che verrà indicizzata. Nella maggior parte dei casi penso che userete lo stesso nome per entrambi. L'argomento finale è un insieme di opzioni. Per ora, ne stiamo usando solo uno, unico. Il primo indice per nome non è unico. Il secondo per email è. Quando archiviamo i dati, IndexedDB controlla questi indici e garantisce che la proprietà email sia unica. Effettuerà anche una certa gestione dei dati sul back-end per garantire che possiamo recuperare i dati da questi indici.

Come funziona? Una volta recuperato un archivio oggetti tramite una transazione, è possibile richiedere un indice da tale archivio. Usando il codice sopra, ecco un esempio di questo:

var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("persone"); var index = store.index ("nome"); // il nome è un valore var request = index.get (name);

Per prima cosa otteniamo la transazione, seguita dal negozio e poi indice. Come abbiamo detto prima, potresti incatenare quelle prime tre linee per renderlo un po 'più compatto, se vuoi.

Una volta ottenuto un indice, puoi eseguire un ottenere chiamaci per recuperare i dati per nome. Potremmo fare qualcosa di simile anche per la posta elettronica. Il risultato di tale chiamata è ancora un altro oggetto asincrono a cui è possibile associare un gestore onsuccess. Ecco un esempio di quel gestore trovato nel file test10.html:

request.onsuccess = function (e) var result = e.target.result; if (result) var s = "

Nome "+ nome +"

"; per (campo var in result) s + = field +" = "+ result [field] +"
"; document.querySelector (" # status "). innerHTML = s; else document.querySelector (" # status "). innerHTML ="

Nessuna corrispondenza

";

Si noti che un indice ottenere la chiamata può restituire più oggetti. Poiché il nostro nome non è univoco, probabilmente dovremmo modificare il codice per gestirlo, ma non è necessario.

Ora diamo un calcio. Hai visto l'utilizzo dell'API get sull'indice per ottenere un valore basato su tale proprietà. Cosa succede se si desidera ottenere un insieme più ampio di dati? Il termine finale che impareremo oggi sono gli intervalli. Gli intervalli rappresentano un modo per selezionare un sottoinsieme di un indice. Ad esempio, dato un indice su una proprietà name, possiamo usare un intervallo per trovare nomi che iniziano con A fino a nomi che iniziano con C. Gli intervalli sono disponibili in diverse varietà. Possono essere "tutto al di sotto di un indicatore", "tutto al di sopra di un indicatore" e "qualcosa tra un marcatore inferiore e un marcatore più alto". Infine, solo per rendere le cose interessanti, le gamme possono essere inclusive o esclusive. Fondamentalmente questo significa che per un intervallo che va da A-C, possiamo specificare se vogliamo includere A e C nell'intervallo o solo i valori tra loro. Infine, puoi anche richiedere sia i campi ascendenti che quelli discendenti.

Gli intervalli vengono creati utilizzando un oggetto di livello elevato denominato IDBKeyRange. Ha tre metodi di interesse: limite inferiore, limite superiore, e limite. limite inferiore viene utilizzato per creare un intervallo che inizia con un valore inferiore e restituisce tutti i dati "sopra" di esso. limite superiore è il contrario. E infine - limite è usato per supportare un insieme di dati con un limite inferiore e uno superiore. Diamo un'occhiata ad alcuni esempi:

// Valori oltre 39 var oldRange = IDBKeyRange.lowerBound (39); // Valori 40a dn su var oldRange2 = IDBKeyRange.lowerBound (40, true); // 39 e smaller ... var youngRange = IDBKeyRange.upperBound (40); // 39 e minori ... var youngRange2 = IDBKeyRange.upperBound (39, true); // non giovani o vecchi ... puoi anche specificare var inclusivo / esclusivo okRange = IDBKeyRange.bound (20,40)

Una volta che hai un intervallo, puoi passarlo al metodo openCursor di un indice. Ciò consente a un iteratore di eseguire il loop dei valori corrispondenti a tale intervallo. In pratica, questa non è in realtà una ricerca di per sé. È possibile utilizzare questo per cercare contenuti in base all'inizio di una stringa, ma non al centro o alla fine. Diamo un'occhiata a un esempio completo. Per prima cosa creeremo un semplice modulo per cercare le persone:

Iniziare con: 
Finire con:

Permetteremo le ricerche che consistono in uno qualsiasi dei tre tipi di intervalli (di nuovo, un valore e più alto, un valore massimo o i valori all'interno di due input). Ora diamo un'occhiata al gestore di eventi per questo modulo.

function getPeople (e) var name = document.querySelector ("# nameSearch"). value; var endname = document.querySelector ("# nameSearchEnd"). value; if (name == "" && endname == "") return; var transaction = db.transaction (["people"], "readonly"); var store = transaction.objectStore ("persone"); var index = store.index ("nome"); // Imposta l'intervallo in base al tipo di intervallo var; if (name! = "" && endname! = "") range = IDBKeyRange.bound (nome, endname);  else if (name == "") range = IDBKeyRange.upperBound (endname);  else range = IDBKeyRange.lowerBound (name);  var s = ""; index.openCursor (range) .onsuccess = function (e) var cursor = e.target.result; if (cursore) s + = "

Tasto "+ cursor.key +"

"; per (campo var in cursor.value) s + = field +" = "+ cursor.value [field] +"
"; s + ="

"; cursor.continue (); document.querySelector (" # status "). innerHTML = s;

Dall'alto verso il basso, iniziamo afferrando i due campi del modulo. Successivamente creiamo una transazione e da quella otteniamo il negozio e l'indice. Ora per la parte semi-complessa. Dal momento che abbiamo tre diversi tipi di intervalli, dobbiamo sostenere che dobbiamo fare un po 'di logica condizionale per capire di cosa abbiamo bisogno. La gamma che creiamo si basa su quali campi compilare. Ciò che è bello è che una volta ottenuto l'intervallo, lo si passa semplicemente all'indice e si apre il cursore. Questo è tutto! Puoi trovare questo esempio completo in test11.html. Assicurati di inserire prima alcuni valori in modo da avere i dati da cercare.


Qual'è il prossimo?

Che ci crediate o no, abbiamo appena iniziato la nostra discussione su IndexedDB. Nel prossimo articolo, tratteremo argomenti aggiuntivi, inclusi aggiornamenti ed eliminazioni, valori basati su array e alcuni suggerimenti generali per lavorare con IndexedDB.