OUJOOD.COM
localStorage et sessionStorage couvrent bien les petits besoins : préférences, état de formulaire, quelques Ko de données. Mais dès que vous avez besoin de stocker des centaines d'enregistrements, de faire des recherches, ou de travailler hors connexion avec une vraie structure de données, ces APIs montrent leurs limites. C'est là qu'IndexedDB entre en jeu.
IndexedDB est une base de données orientée objets, intégrée nativement dans tous les navigateurs modernes. Elle stocke des objets JavaScript directement — pas besoin de tout convertir en chaîne. Sa capacité de stockage se compte en dizaines ou centaines de Mo selon le navigateur et les permissions accordées par l'utilisateur.
Concepts clés avant de commencer
IndexedDB fonctionne différemment d'une base SQL classique. Quelques notions à bien avoir en tête :
- Base de données : un conteneur lié à un domaine, avec un numéro de version.
- Object Store : l'équivalent d'une table. On y stocke des objets JS identifiés par une clé.
- Transaction : toute opération (lecture ou écriture) passe par une transaction. C'est le mécanisme qui garantit la cohérence des données.
- Index : permet de rechercher des enregistrements par d'autres propriétés que la clé principale.
- Asynchrone : toutes les opérations sont non bloquantes. On travaille avec des événements (
onsuccess,onerror) ou des Promises.
Ouvrir une base de données
La première étape est toujours d'ouvrir (ou créer) la base. Si elle n'existe pas encore, le navigateur la crée automatiquement. L'événement onupgradeneeded est le seul endroit où l'on peut créer ou modifier la structure des object stores :
Exemple : 📋 Copier le code
// Ouvrir la base "maBoutique" en version 1 const requete = indexedDB.open('maBoutique', 1); // Déclenché uniquement lors de la création ou d'un changement de version requete.onupgradeneeded = (event) => { const db = event.target.result; // Créer un object store "produits" avec un id auto-incrémenté const store = db.createObjectStore('produits', { keyPath: 'id', autoIncrement: true }); // Ajouter un index sur le nom pour pouvoir chercher par nom store.createIndex('nom', 'nom', { unique: false }); }; requete.onsuccess = (event) => { const db = event.target.result; console.log('Base ouverte :', db.name); }; requete.onerror = (event) => { console.error('Erreur ouverture :', event.target.error); };
Ajouter des enregistrements
Pour écrire dans IndexedDB, on ouvre une transaction en mode readwrite, puis on accède à l'object store cible :
Exemple : 📋 Copier le code
// Ajouter un produit dans l'object store "produits" function ajouterProduit(db, produit) { const transaction = db.transaction('produits', 'readwrite'); const store = transaction.objectStore('produits'); const requete = store.add(produit); requete.onsuccess = () => { console.log('Produit ajouté, id :', requete.result); }; requete.onerror = () => { console.error('Erreur ajout :', requete.error); }; } // Utilisation ajouterProduit(db, { nom: 'Clavier mécanique', prix: 89.99, stock: 15 }); ajouterProduit(db, { nom: 'Souris sans fil', prix: 34.50, stock: 42 });
Lire un enregistrement par sa clé
La lecture utilise une transaction en mode readonly (moins coûteux que readwrite). On récupère un enregistrement précis via sa clé :
Exemple : 📋 Copier le code
// Lire le produit avec l'id 1
function lireProduit(db, id) {
const transaction = db.transaction('produits', 'readonly');
const store = transaction.objectStore('produits');
const requete = store.get(id);
requete.onsuccess = () => {
if (requete.result) {
console.log('Produit trouvé :', requete.result);
} else {
console.log('Aucun produit avec cet id.');
}
};
}
lireProduit(db, 1);
Lire tous les enregistrements
Pour récupérer l'ensemble des enregistrements d'un object store, on utilise getAll() — disponible dans tous les navigateurs modernes :
Exemple : 📋 Copier le code
// Récupérer tous les produits function tousLesProduits(db) { const transaction = db.transaction('produits', 'readonly'); const store = transaction.objectStore('produits'); const requete = store.getAll(); requete.onsuccess = () => { console.log('Tous les produits :', requete.result); // requete.result est un tableau d'objets JS }; } tousLesProduits(db);
Mettre à jour un enregistrement
put() remplace un enregistrement existant ou en crée un nouveau si la clé n'existe pas encore — le comportement d'un "upsert" :
Exemple : 📋 Copier le code
// Mettre à jour le stock du produit id=1 function mettreAJourProduit(db, produitModifie) { const transaction = db.transaction('produits', 'readwrite'); const store = transaction.objectStore('produits'); // put() remplace l'enregistrement complet const requete = store.put(produitModifie); requete.onsuccess = () => { console.log('Produit mis à jour.'); }; } mettreAJourProduit(db, { id: 1, nom: 'Clavier mécanique', prix: 79.99, stock: 10 });
Supprimer un enregistrement
Exemple : 📋 Copier le code
// Supprimer le produit avec l'id 2
function supprimerProduit(db, id) {
const transaction = db.transaction('produits', 'readwrite');
const store = transaction.objectStore('produits');
const requete = store.delete(id);
requete.onsuccess = () => {
console.log('Produit supprimé.');
};
}
supprimerProduit(db, 2);
Rechercher avec un index
L'index créé sur la propriété nom lors de l'ouverture de la base permet de chercher des enregistrements sans connaître leur clé principale :
Exemple : 📋 Copier le code
// Rechercher un produit par son nom via l'index
function rechercherParNom(db, nomRecherche) {
const transaction = db.transaction('produits', 'readonly');
const store = transaction.objectStore('produits');
const index = store.index('nom');
const requete = index.get(nomRecherche);
requete.onsuccess = () => {
if (requete.result) {
console.log('Produit trouvé :', requete.result);
} else {
console.log('Aucun produit avec ce nom.');
}
};
}
rechercherParNom(db, 'Souris sans fil');
IndexedDB vs localStorage : que choisir ?
Le choix dépend du volume et de la complexité des données :
- localStorage : préférences, petites chaînes, données simples. Rapide à mettre en place, synchrone.
- IndexedDB : catalogues de produits, messages, données de formulaires complexes, applications hors ligne. Asynchrone, structuré, puissant.
En pratique, si vous stockez plus de 50 enregistrements ou si vos données ont une structure complexe, IndexedDB est le bon choix.
Par carabde | Mis à jour le 17 avril 2026