HTML - IndexedDB

-

Introduction à IndexedDB

IndexedDB est une API de bas niveau pour le stockage côté client de grandes quantités de données structurées dans les navigateurs web. Elle offre un moyen de stocker et de récupérer des données localement, permettant aux applications web de fonctionner hors ligne et d'offrir une bonne expérience utilisateur.

IndexedDB est une base de données NoSQL qui utilise un stockage clé-valeur et prend en charge les transactions et les index. Elle vous permet de stocker et de récupérer des objets JavaScript, y compris des types de données complexes comme les tableaux et les objets imbriqués. IndexedDB offre une capacité de stockage supérieure par rapport à d'autres options de stockage côté client comme les cookies et localStorage.

L'un des principaux avantages d'IndexedDB est sa capacité à bien gérer de grandes quantités de données structurées. Elle convient aux applications nécessitant un stockage local persistant, telles que les applications web hors ligne, les applications web progressives (PWA) et les applications à forte intensité de données. IndexedDB propose des opérations asynchrones, ce qui signifie qu'elle ne bloque pas le thread principal d'exécution, résultant en de meilleures performances et réactivité.

Par rapport à d'autres méthodes de stockage comme les cookies et localStorage, IndexedDB présente plusieurs avantages :

Aspect IndexedDB Cookies localStorage
Capacité de stockage Gigaoctets Environ 4 Ko Généralement jusqu'à 5-10 Mo
Données structurées Prend en charge le stockage d'objets JavaScript complexes et des requêtes efficaces grâce aux index Limité au stockage de paires clé-valeur de chaînes Limité au stockage de paires clé-valeur de chaînes
API asynchrone Les opérations sont asynchrones, résultant en de meilleures performances et réactivité Synchrone, peut bloquer le thread principal Synchrone, peut bloquer le thread principal
Support transactionnel Fournit un modèle transactionnel pour les opérations de données, assurant l'intégrité des données Pas de support transactionnel Pas de support transactionnel
Indexation et requêtes Prend en charge la création d'index sur les propriétés des magasins d'objets pour des recherches et des requêtes rapides Pas de capacités d'indexation ou de requêtes Pas de capacités d'indexation ou de requêtes

En utilisant IndexedDB, les développeurs web peuvent créer des applications qui fonctionnent bien en ligne et hors ligne, offrant une bonne expérience utilisateur et gérant de grandes quantités de données structurées.

Concepts de base

Pour travailler avec IndexedDB, il faut comprendre quelques concepts fondamentaux. IndexedDB est basé sur un stockage clé-valeur, ce qui signifie que les données sont stockées et récupérées à l'aide de clés uniques associées à chaque valeur.

Au cœur d'IndexedDB se trouvent les magasins d'objets. Un magasin d'objets est comparable à une table dans une base de données traditionnelle et contient les données réelles. Chaque magasin d'objets a un nom et peut stocker des objets JavaScript de tout type, y compris des structures de données complexes. Les magasins d'objets sont créés au sein d'une base de données et servent à organiser et regrouper les données connexes.

Conseil: Création d'un magasin d'objets

let request = indexedDB.open("MyDatabase", 1);

request.onupgradeneeded = function(event) {
  let db = event.target.result;
  let objectStore = db.createObjectStore("MyObjectStore", { keyPath: "id" });
};

Les transactions sont un élément fondamental d'IndexedDB. Toutes les opérations sur les données, comme la lecture, l'écriture ou la suppression, doivent se produire au sein d'une transaction. Les transactions offrent un moyen de regrouper plusieurs opérations et de maintenir l'intégrité des données. Elles peuvent être en lecture seule ou en lecture-écriture, selon le type d'opérations effectuées. Si une opération au sein d'une transaction échoue, toute la transaction est annulée et la base de données reste inchangée.

Conseil: Utilisation d'une transaction

let db = event.target.result;
let transaction = db.transaction(["MyObjectStore"], "readwrite");
let objectStore = transaction.objectStore("MyObjectStore");

let request = objectStore.add({ id: 1, name: "John Doe" });

request.onsuccess = function(event) {
  console.log("Les données ont été ajoutées à votre base de données.");
};

request.onerror = function(event) {
  console.log("Impossible d'ajouter les données à votre base de données.");
};

Les index sont un autre concept important dans IndexedDB. Un index est un moyen de rechercher et de récupérer des données d'un magasin d'objets basé sur une propriété spécifique ou un ensemble de propriétés. Les index permettent de trouver rapidement des données sans avoir à parcourir l'ensemble du magasin d'objets. Vous pouvez créer des index sur n'importe quelle propriété des objets stockés dans un magasin d'objets, et vous pouvez également créer des index composés qui combinent plusieurs propriétés.

Conseil: Création d'un index

let objectStore = db.createObjectStore("MyObjectStore", { keyPath: "id" });
objectStore.createIndex("name", "name", { unique: false });

Configuration d'IndexedDB

Avant de commencer à utiliser IndexedDB dans votre application web, vous devez le configurer. Cela implique de vérifier la prise en charge par le navigateur, d'ouvrir une base de données, de créer des magasins d'objets et de définir des index.

Il est important de vérifier si le navigateur prend en charge IndexedDB. Vous pouvez le faire en vérifiant si la propriété indexedDB existe sur l'objet window.

Conseil: Vérification de la prise en charge d'IndexedDB

if (window.indexedDB) {
  console.log("IndexedDB est pris en charge");
} else {
  console.log("IndexedDB n'est pas pris en charge");
}

Une fois que vous avez confirmé qu'IndexedDB est pris en charge, l'étape suivante consiste à ouvrir une base de données. Vous pouvez ouvrir une base de données en appelant la méthode open() sur l'objet indexedDB. Cette méthode prend deux paramètres : le nom de la base de données et le numéro de version. Si la base de données n'existe pas, elle sera créée ; sinon, la base de données existante sera ouverte.

Conseil: Ouverture d'une base de données

let request = indexedDB.open("MaBaseDeDonnees", 1);

request.onerror = function(event) {
  console.log("Erreur lors de l'ouverture de la base de données");
};

request.onsuccess = function(event) {
  let db = event.target.result;
  console.log("Base de données ouverte avec succès");
};

Lors de l'ouverture d'une base de données, vous pouvez également spécifier un numéro de version. Si le numéro de version est supérieur à la version existante, l'événement onupgradeneeded sera déclenché, vous permettant de modifier la structure de la base de données, comme la création ou la modification de magasins d'objets et d'index.

Dans le gestionnaire d'événements onupgradeneeded, vous pouvez créer des magasins d'objets en utilisant la méthode createObjectStore() sur l'objet de base de données. Vous devez fournir un nom pour le magasin d'objets et spécifier le chemin de la clé, qui est la propriété qui identifie de manière unique chaque objet dans le magasin.

Conseil: Création d'un magasin d'objets

request.onupgradeneeded = function(event) {
  let db = event.target.result;
  let objectStore = db.createObjectStore("MonMagasinObjets", { keyPath: "id" });
};

Après avoir créé un magasin d'objets, vous pouvez définir des index sur des propriétés spécifiques des objets stockés dans le magasin d'objets. Les index vous permettent de rechercher et d'obtenir des données basées sur ces propriétés. Pour créer un index, vous pouvez utiliser la méthode createIndex() sur le magasin d'objets.

Conseil: Définition des index

request.onupgradeneeded = function(event) {
  let db = event.target.result;
  let objectStore = db.createObjectStore("MonMagasinObjets", { keyPath: "id" });
  objectStore.createIndex("nom", "nom", { unique: false });
  objectStore.createIndex("age", "age", { unique: false });
};

Nous créons deux index : un sur la propriété "nom" et un autre sur la propriété "age". Le paramètre unique spécifie si les valeurs de l'index doivent être uniques ou non.

Effectuer des opérations CRUD

Création de données

Pour ajouter des données à un magasin d'objets dans IndexedDB, vous devez utiliser des transactions. Ouvrez d'abord une transaction sur le magasin d'objets souhaité en mode "readwrite". Ensuite, obtenez une référence au magasin d'objets en utilisant la méthode objectStore() sur l'objet de transaction. Enfin, utilisez la méthode add() ou put() sur le magasin d'objets pour ajouter les données.

Conseil: Ajouter des données à IndexedDB

let db;
let request = indexedDB.open("MyDatabase", 1);

request.onsuccess = function(event) {
  db = event.target.result;
  addData({ id: 1, name: "John Doe", age: 25 });
};

function addData(data) {
  let transaction = db.transaction(["MyObjectStore"], "readwrite");
  let objectStore = transaction.objectStore("MyObjectStore");

  let request = objectStore.add(data);

  request.onsuccess = function(event) {
    console.log("Données ajoutées avec succès");
  };

  request.onerror = function(event) {
    console.log("Erreur lors de l'ajout des données");
  };
}

La méthode add() est utilisée pour ajouter de nouvelles données, tandis que la méthode put() peut être utilisée pour ajouter de nouvelles données ou mettre à jour des données existantes si la clé existe déjà.

Il est important de gérer les erreurs qui peuvent survenir pendant le processus d'ajout de données. Vous pouvez utiliser le gestionnaire d'événements onerror sur l'objet de requête pour capturer et gérer les erreurs.

Lecture de données

Pour obtenir des données d'un magasin d'objets, vous pouvez utiliser la méthode get() sur le magasin d'objets. Vous devez fournir la clé des données que vous souhaitez obtenir.

Conseil: Obtenir des données d'IndexedDB

let transaction = db.transaction(["MyObjectStore"], "readonly");
let objectStore = transaction.objectStore("MyObjectStore");

let request = objectStore.get(1);

request.onsuccess = function(event) {
  let data = event.target.result;
  console.log("Données récupérées :", data);
};

Si vous voulez rechercher des données basées sur une propriété spécifique, vous pouvez utiliser des index. Obtenez d'abord une référence à l'index en utilisant la méthode index() sur le magasin d'objets. Ensuite, utilisez la méthode get() sur l'index pour obtenir des données basées sur la clé de l'index.

Conseil: Utiliser des index pour obtenir des données

let transaction = db.transaction(["MyObjectStore"], "readonly");
let objectStore = transaction.objectStore("MyObjectStore");
let index = objectStore.index("name");

let request = index.get("John Doe");

request.onsuccess = function(event) {
  let data = event.target.result;
  console.log("Données récupérées :", data);
};

Pour des requêtes plus avancées ou pour parcourir plusieurs entrées de données, vous pouvez utiliser des curseurs. Les curseurs vous permettent de parcourir toutes les données d'un magasin d'objets ou d'un index. Vous pouvez ouvrir un curseur en utilisant la méthode openCursor() sur le magasin d'objets ou l'index.

Conseil: Utiliser des curseurs dans IndexedDB

let transaction = db.transaction(["MyObjectStore"], "readonly");
let objectStore = transaction.objectStore("MyObjectStore");

let request = objectStore.openCursor();

request.onsuccess = function(event) {
  let cursor = event.target.result;
  if (cursor) {
    console.log("Clé :", cursor.key);
    console.log("Données :", cursor.value);
    cursor.continue();
  } else {
    console.log("Plus de données");
  }
};

Dans l'exemple ci-dessus, nous ouvrons un curseur sur le magasin d'objets. Le gestionnaire d'événements onsuccess est appelé pour chaque entrée de données. Nous pouvons accéder à la clé et à la valeur de l'entrée actuelle en utilisant respectivement cursor.key et cursor.value. Pour passer à l'entrée suivante, nous appelons la méthode continue() sur le curseur.

Mise à jour des données

Pour mettre à jour des données existantes dans un magasin d'objets, vous pouvez utiliser la méthode put(). Elle fonctionne de manière similaire à la méthode add(), mais si la clé existe déjà, elle mettra à jour les données correspondantes.

Conseil: Mettre à jour des données dans IndexedDB

let transaction = db.transaction(["MyObjectStore"], "readwrite");
let objectStore = transaction.objectStore("MyObjectStore");

let updatedData = { id: 1, name: "John Doe", age: 26 };
let request = objectStore.put(updatedData);

request.onsuccess = function(event) {
  console.log("Données mises à jour avec succès");
};

Vous pouvez également mettre à jour des champs spécifiques d'une entrée de données existante en utilisant la méthode put(). Obtenez d'abord les données en utilisant la méthode get(), mettez à jour les champs souhaités, puis utilisez put() pour enregistrer les modifications.

Conseil: Mettre à jour partiellement des données dans IndexedDB

let transaction = db.transaction(["MyObjectStore"], "readwrite");
let objectStore = transaction.objectStore("MyObjectStore");

let request = objectStore.get(1);

request.onsuccess = function(event) {
  let data = event.target.result;
  data.age = 27;

  let updateRequest = objectStore.put(data);

  updateRequest.onsuccess = function(event) {
    console.log("Données mises à jour avec succès");
  };
};

Lors de la mise à jour des données, soyez attentif aux changements de version et de schéma. Si vous devez modifier la structure de vos magasins d'objets ou de vos index, vous devez le gérer dans le gestionnaire d'événements onupgradeneeded et versionner correctement votre base de données.

Suppression de données

Pour supprimer des données d'un magasin d'objets, vous pouvez utiliser la méthode delete() sur le magasin d'objets. Vous devez fournir la clé des données que vous souhaitez supprimer.

Conseil: Supprimer des données d'IndexedDB

let transaction = db.transaction(["MyObjectStore"], "readwrite");
let objectStore = transaction.objectStore("MyObjectStore");

let request = objectStore.delete(1);

request.onsuccess = function(event) {
  console.log("Données supprimées avec succès");
};

Si vous voulez effacer un magasin d'objets entier, vous pouvez utiliser la méthode clear() sur le magasin d'objets.

Conseil: Effacer un magasin d'objets IndexedDB

let transaction = db.transaction(["MyObjectStore"], "readwrite");
let objectStore = transaction.objectStore("MyObjectStore");

let request = objectStore.clear();

request.onsuccess = function(event) {
  console.log("Magasin d'objets effacé avec succès");
};

Pour supprimer une base de données, vous pouvez utiliser la méthode deleteDatabase() sur l'objet indexedDB. Cela supprimera complètement la base de données et tous ses magasins d'objets.

Conseil: Supprimer une base de données IndexedDB

let request = indexedDB.deleteDatabase("MyDatabase");

request.onsuccess = function(event) {
  console.log("Base de données supprimée avec succès");
};

Soyez prudent lors de la suppression de données, car il s'agit d'une opération permanente qui ne peut pas être annulée. Voici la traduction en français :

Fonctionnalités avancées

IndexedDB dispose de plusieurs fonctionnalités avancées qui vous permettent de gérer et d'optimiser les données de manière plus complexe. Examinons certaines de ces fonctionnalités en détail.

Gestion des versions et mises à niveau

IndexedDB utilise la gestion des versions pour gérer les changements de structure de la base de données au fil du temps. Chaque base de données a un numéro de version qui lui est associé. Lorsque vous ouvrez une base de données avec un numéro de version supérieur à celui actuel, l'événement onupgradeneeded est déclenché, vous permettant de modifier le schéma de la base de données.

Conseil: Gestion des versions et mises à niveau

let request = indexedDB.open("MaBaseDeDonnees", 2); // Mise à niveau vers la version 2

request.onupgradeneeded = function(event) {
  let db = event.target.result;

  // Effectuer les changements de schéma de la base de données
  if (event.oldVersion < 1) {
    // Créer des object stores et des index pour la version 1
    let objectStore = db.createObjectStore("MonObjectStore", { keyPath: "id" });
    objectStore.createIndex("nom", "nom", { unique: false });
  }

  if (event.oldVersion < 2) {
    // Effectuer les changements pour la version 2
    let objectStore = db.createObjectStore("AutreObjectStore", { keyPath: "id" });
    objectStore.createIndex("categorie", "categorie", { unique: false });
  }
};

Dans l'exemple ci-dessus, nous ouvrons la base de données avec la version 2. Si la version actuelle est inférieure à 2, l'événement onupgradeneeded est déclenché. Nous pouvons alors vérifier la propriété oldVersion pour connaître la version actuelle et effectuer les changements de schéma nécessaires pour chaque mise à niveau de version.

Index et clés composées

Les index dans IndexedDB vous permettent d'interroger et de rechercher des données efficacement en fonction de propriétés spécifiques. Vous pouvez créer des index sur des propriétés uniques ou créer des index composés qui combinent plusieurs propriétés.

Conseil: Index et clés composées

let request = indexedDB.open("MaBaseDeDonnees", 1);

request.onupgradeneeded = function(event) {
  let db = event.target.result;
  let objectStore = db.createObjectStore("MonObjectStore", { keyPath: "id" });

  // Créer un index sur une propriété unique
  objectStore.createIndex("nom", "nom", { unique: false });

  // Créer un index composé
  objectStore.createIndex("nomAge", ["nom", "age"], { unique: false });
};

Dans l'exemple ci-dessus, nous créons un index sur la propriété unique "nom" et un index composé sur les propriétés "nom" et "age". Les index composés vous permettent d'interroger les données en fonction de plusieurs propriétés en même temps.

Transactions et concurrence

Les transactions dans IndexedDB garantissent que les données sont correctes et cohérentes. Toutes les opérations de base de données doivent être effectuées dans le cadre d'une transaction. Les transactions peuvent être en lecture seule ou en lecture-écriture, selon le type d'opérations effectuées.

IndexedDB prend également en charge l'accès concurrent à la base de données. Plusieurs transactions peuvent être actives en même temps, mais elles opèrent sur différents object stores ou ont différents modes d'accès (lecture seule ou lecture-écriture) pour éviter les conflits.

Conseil: Transactions et concurrence

let transaction1 = db.transaction(["ObjectStore1"], "readonly");
let transaction2 = db.transaction(["ObjectStore2"], "readwrite");

// Plusieurs transactions peuvent être actives simultanément
transaction1.objectStore("ObjectStore1").get(1);
transaction2.objectStore("ObjectStore2").add({ id: 1, nom: "Jean" });

Dans l'exemple ci-dessus, nous avons deux transactions actives en même temps. transaction1 est en lecture seule et opère sur "ObjectStore1", tandis que transaction2 est en lecture-écriture et opère sur "ObjectStore2". Elles peuvent se dérouler indépendamment sans conflits.

Considérations de performance

Pour optimiser les performances de votre utilisation d'IndexedDB, tenez compte des points suivants :

Considération Description
Utiliser des index appropriés Créez des index sur les propriétés que vous utilisez fréquemment pour les requêtes ou les recherches. Les index accélèrent les opérations de récupération de données.
Minimiser la portée des transactions Gardez les transactions aussi petites que possible et n'incluez que les opérations nécessaires. Cela aide à réduire la durée de verrouillage et améliore la concurrence.
Utiliser des opérations par lots Si vous devez effectuer plusieurs opérations d'écriture, envisagez d'utiliser des opérations par lots comme add(), put(), ou delete() au sein d'une seule transaction. Cela minimise la surcharge de création de transactions séparées pour chaque opération.
Éviter la récupération inutile de données Ne récupérez que les données dont vous avez besoin. Utilisez des index et des plages de clés pour réduire l'ensemble des résultats et éviter de récupérer des données inutiles.
Gérer efficacement les grands ensembles de données Si vous traitez de grandes quantités de données, envisagez d'utiliser des techniques comme la pagination ou le chargement paresseux pour charger les données par petits morceaux selon les besoins.

En gardant à l'esprit ces considérations de performance et en utilisant judicieusement les index, les transactions et la concurrence, vous pouvez créer des applications web efficaces et rapides avec IndexedDB.

Sécurité

Lors de l'utilisation d'IndexedDB pour stocker des données dans une application web, il est important de penser à la sécurité et de protéger les informations sensibles. Voici les aspects clés de la gestion des données sensibles et de la sécurisation de l'accès à IndexedDB :

Gestion des données sensibles

Si votre application traite des données sensibles, telles que des informations personnelles ou des détails financiers, vous devez prendre des précautions supplémentaires lors du stockage et de la manipulation de ces données dans IndexedDB. Voici quelques bonnes pratiques :

  1. Chiffrer les données sensibles : Avant de stocker des informations sensibles dans IndexedDB, chiffrez-les en utilisant un algorithme de chiffrement fort. Ainsi, même si quelqu'un accède aux données IndexedDB, il ne pourra pas lire les informations sensibles sans la clé de chiffrement.

  2. Utiliser des bibliothèques de chiffrement sécurisées : Utilisez des bibliothèques ou des algorithmes de chiffrement bien établis et fiables, tels que AES (Advanced Encryption Standard), pour chiffrer et déchiffrer les données sensibles. Ne créez pas vos propres algorithmes de chiffrement, car ils peuvent comporter des vulnérabilités.

  3. Stocker les clés de chiffrement de manière sécurisée : Gardez les clés de chiffrement utilisées pour chiffrer et déchiffrer les données sensibles en sécurité. Ne les stockez pas dans la même base de données que les données chiffrées. Envisagez plutôt d'utiliser des techniques comme les fonctions de dérivation de clé ou des mécanismes de stockage sécurisé de clés fournis par la plateforme ou le navigateur.

  4. Minimiser la conservation des données : Ne stockez des données sensibles dans IndexedDB que lorsque c'est absolument nécessaire. Si les données ne sont plus nécessaires, supprimez-les de manière sécurisée de la base de données. Examinez et supprimez régulièrement toute information sensible inutile pour réduire le risque de fuites de données.

Sécurisation de l'accès à IndexedDB

En plus de gérer les données sensibles de manière sécurisée, vous devez également contrôler l'accès à IndexedDB pour empêcher les accès ou les modifications non autorisés. Voici quelques mesures que vous pouvez prendre :

  1. Utiliser les fonctions de sécurité du navigateur : Utilisez les fonctions de sécurité du navigateur comme la politique de même origine (Same-Origin Policy) et la politique de sécurité du contenu (Content Security Policy - CSP) pour restreindre l'accès à IndexedDB depuis des sources non fiables. Ces politiques aident à prévenir les attaques de type cross-site scripting (XSS) et les accès non autorisés à IndexedDB depuis différentes origines.

Conseil: Exemple de politique de même origine

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
  1. Implémenter l'authentification des utilisateurs : Si votre application nécessite une authentification des utilisateurs, assurez-vous que seuls les utilisateurs authentifiés peuvent accéder aux données IndexedDB. Utilisez des mécanismes d'authentification sécurisés, tels que des jetons ou la gestion de session, pour vérifier l'identité de l'utilisateur avant d'accorder l'accès à la base de données.

Conseil: Exemple de gestion de session sécurisée

// Exemple d'authentification basée sur un jeton
fetch('https://api.example.com/data', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer ' + token
  }
})
  .then(response => response.json())
  .then(data => console.log(data));
  1. Appliquer des contrôles d'accès : Implémentez des contrôles d'accès basés sur les rôles ou les permissions des utilisateurs. Décidez quels utilisateurs ou groupes d'utilisateurs doivent avoir un accès en lecture ou en écriture à des object stores ou des données spécifiques dans IndexedDB. Utilisez ces contrôles d'accès de manière cohérente dans toute votre application.

  2. Valider et assainir les entrées utilisateur : Lorsque vous acceptez des entrées utilisateur qui seront stockées dans IndexedDB, validez et assainissez ces entrées pour prévenir les vulnérabilités de sécurité potentielles comme les injections SQL ou les attaques de type cross-site scripting. Utilisez des règles de validation strictes et échappez ou supprimez tout caractère ou script malveillant.

Conseil: Exemple de validation des entrées utilisateur

const sanitizedInput = input.replace(/[<>]/g, ''); // assainissement simple
  1. Utiliser une communication sécurisée : Si votre application communique avec un serveur pour synchroniser les données IndexedDB, assurez-vous que le canal de communication est sécurisé. Utilisez HTTPS/SSL pour chiffrer les données transmises entre le client et le serveur, empêchant ainsi l'écoute ou la falsification.

Conseil: Exemple de communication HTTPS

<form action="https://yourserver.com/submit" method="post">
  <input type="text" name="data">
  <input type="submit" value="Submit">
</form>

N'oubliez pas que la sécurité est un processus continu, et il est important de rester à jour avec les meilleures pratiques de sécurité et les vulnérabilités les plus récentes. Examinez et mettez à jour régulièrement vos mesures de sécurité pour protéger les données sensibles et maintenir votre implémentation IndexedDB en sécurité.

Compatibilité des navigateurs et solutions de rechange

Lors de l'utilisation d'IndexedDB dans votre application web, vous devez tenir compte de la compatibilité des navigateurs et prévoir des stratégies de repli pour les navigateurs qui ne prennent pas en charge IndexedDB ou qui ont un support limité.

La prise en charge d'IndexedDB par les navigateurs s'est améliorée au fil du temps, la plupart des navigateurs modernes offrant désormais un bon support pour cette API. Cependant, il peut encore exister des navigateurs plus anciens ou des appareils mobiles qui ont un support limité ou inexistant pour IndexedDB.

Pour vérifier si un navigateur prend en charge IndexedDB, vous pouvez utiliser une technique simple de détection de fonctionnalités :

Conseil: Détection de la prise en charge d'IndexedDB

if (window.indexedDB) {
  console.log("IndexedDB est pris en charge");
} else {
  console.log("IndexedDB n'est pas pris en charge");
}

Si IndexedDB n'est pas pris en charge dans un navigateur, vous devrez prévoir des stratégies de repli pour gérer le stockage et la récupération des données. Une approche courante consiste à utiliser d'autres mécanismes de stockage comme solutions de rechange, tels que le Web Storage (localStorage ou sessionStorage) ou les cookies. Ces alternatives peuvent avoir des limitations par rapport à IndexedDB, comme une capacité de stockage plus faible ou l'absence de fonctionnalités avancées telles que l'indexation et les transactions, mais elles peuvent tout de même fournir un niveau de base de persistance des données.

Conseil: Stratégies de repli pour le stockage de données

if (window.indexedDB) {
  // Utiliser IndexedDB
  let request = indexedDB.open("MaBase", 1);
  // ...
} else if (window.localStorage) {
  // Repli vers localStorage
  localStorage.setItem("clé", "valeur");
  // ...
} else {
  console.log("Aucun mécanisme de stockage disponible");
}

Une autre option consiste à utiliser des polyfills ou des bibliothèques qui fournissent une API cohérente pour IndexedDB tout en gérant en interne les différences entre navigateurs et les solutions de repli. Ces outils visent à combler les lacunes dans la prise en charge des navigateurs et permettent aux développeurs d'utiliser IndexedDB de manière plus indépendante du navigateur.

Voici quelques polyfills et bibliothèques populaires pour IndexedDB :

Polyfill/Bibliothèque Description
IndexedDBShim Un polyfill qui ajoute la prise en charge d'IndexedDB dans les navigateurs qui n'ont pas de support natif.
localForage Une bibliothèque qui fournit une API simple et cohérente pour le stockage de données côté client, y compris IndexedDB, Web Storage et WebSQL.
Dexie.js Une bibliothèque wrapper pour IndexedDB qui fournit une API plus intuitive et concise pour travailler avec IndexedDB.

Conseil: Inclure le polyfill IndexedDBShim

<!-- Inclure le polyfill IndexedDBShim -->
<script src="indexeddbshim.min.js"></script>

Conseil: Utiliser IndexedDB comme d'habitude

// Utiliser IndexedDB comme d'habitude
let request = indexedDB.open("MaBase", 1);
// ...

Lorsque vous utilisez des polyfills ou des bibliothèques, assurez-vous de consulter leur documentation et de prendre en compte leur prise en charge des navigateurs, leur impact sur les performances et les limitations qu'ils peuvent avoir.

N'oubliez pas de tester votre application web sur différents navigateurs et appareils pour vous assurer que les stratégies de repli fonctionnent comme prévu et offrent une bonne expérience utilisateur, même dans les navigateurs sans prise en charge d'IndexedDB. Voici la traduction en français du texte fourni :

Exemples pratiques et cas d'utilisation

IndexedDB est un outil puissant qui peut être utilisé dans divers scénarios pratiques pour améliorer la fonctionnalité et l'expérience utilisateur des applications web. Examinons quelques cas d'utilisation courants et des exemples où IndexedDB excelle.

Stockage de données hors ligne et synchronisation

L'un des principaux avantages d'IndexedDB est sa capacité à stocker des données hors ligne et à permettre une fonctionnalité hors ligne dans les applications web. Avec IndexedDB, vous pouvez stocker les données de l'application localement sur l'appareil de l'utilisateur, leur permettant d'accéder à l'application et d'interagir avec elle même lorsqu'ils ne sont pas connectés à Internet.

Conseil: Stocker des données hors ligne

// Stocker des données hors ligne
function storeDataOffline(data) {
  let transaction = db.transaction(["MyObjectStore"], "readwrite");
  let objectStore = transaction.objectStore("MyObjectStore");

  let request = objectStore.add(data);

  request.onsuccess = function(event) {
    console.log("Données stockées hors ligne");
  };
}

// Synchroniser les données une fois en ligne
function syncDataWithServer() {
  let transaction = db.transaction(["MyObjectStore"], "readonly");
  let objectStore = transaction.objectStore("MyObjectStore");

  let request = objectStore.openCursor();

  request.onsuccess = function(event) {
    let cursor = event.target.result;
    if (cursor) {
      let data = cursor.value;
      sendDataToServer(data);
      cursor.continue();
    } else {
      console.log("Toutes les données synchronisées avec le serveur");
    }
  };
}

// Envoyer les données au serveur
function sendDataToServer(data) {
  fetch('https://api.example.com/data', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  })
    .then(response => {
      if (response.ok) {
        console.log("Données synchronisées avec le serveur");
      }
    });
}

La fonction storeDataOffline stocke les données dans IndexedDB lorsque l'application est hors ligne. Les données sont ajoutées à un object store dans une transaction. Plus tard, lorsque l'application se reconnecte, la fonction syncDataWithServer utilise un curseur pour parcourir toutes les données stockées et envoie chaque élément de données au serveur en utilisant la fonction sendDataToServer. Ainsi, l'application peut fonctionner hors ligne et synchroniser les données avec le serveur lorsque la connexion est rétablie.

Mise en cache des données de l'application

IndexedDB peut être utilisé comme mécanisme de mise en cache pour stocker localement des données fréquemment consultées ou lentes à charger. En mettant en cache les données dans IndexedDB, vous pouvez améliorer les performances et la vitesse de votre application web.

Conseil: Vérifier le cache pour les données

// Vérifier le cache pour les données
function getDataFromCache(key) {
  return new Promise((resolve, reject) => {
    let transaction = db.transaction(["CacheStore"], "readonly");
    let objectStore = transaction.objectStore("CacheStore");

    let request = objectStore.get(key);

    request.onsuccess = function(event) {
      let data = event.target.result;
      if (data) {
        console.log("Données récupérées du cache");
        resolve(data);
      } else {
        console.log("Données non trouvées dans le cache");
        reject();
      }
    };
  });
}

// Stocker les données dans le cache
function storeDataInCache(key, data) {
  let transaction = db.transaction(["CacheStore"], "readwrite");
  let objectStore = transaction.objectStore("CacheStore");

  let request = objectStore.put(data, key);

  request.onsuccess = function(event) {
    console.log("Données stockées dans le cache");
  };
}

// Obtenir les données du cache ou les récupérer du serveur
function getData(key) {
  getDataFromCache(key)
    .then(data => {
      console.log("Données récupérées du cache :", data);
    })
    .catch(() => {
      fetch(`https://api.example.com/data/${key}`)
        .then(response => response.json())
        .then(data => {
          console.log("Données récupérées du serveur :", data);
          storeDataInCache(key, data);
        });
    });
}

La fonction getDataFromCache vérifie si les données demandées sont disponibles dans le cache (IndexedDB). Si les données sont trouvées, elles sont résolues et renvoyées. Si les données ne sont pas trouvées dans le cache, la fonction rejette, et la fonction getData récupère les données du serveur en utilisant l'API fetch. Une fois les données récupérées du serveur, elles sont stockées dans le cache à l'aide de la fonction storeDataInCache pour un accès futur.

En implémentant ce mécanisme de mise en cache, vous pouvez réduire le nombre de requêtes réseau et améliorer la vitesse de chargement de votre application en servant les données depuis le cache local lorsqu'elles sont disponibles.

Implémentation de la fonctionnalité de recherche

Les capacités d'indexation d'IndexedDB le rendent bien adapté pour implémenter une fonctionnalité de recherche dans une application web. En créant des index sur les champs recherchables, vous pouvez rapidement rechercher et récupérer des données basées sur des critères spécifiques.

Conseil: Créer un index sur un champ recherchable

// Créer un index sur un champ recherchable
function createSearchIndex() {
  let request = indexedDB.open("MyDatabase", 1);

  request.onupgradeneeded = function(event) {
    let db = event.target.result;
    let objectStore = db.createObjectStore("ProductStore", { keyPath: "id" });
    objectStore.createIndex("name", "name", { unique: false });
  };
}

// Rechercher des données en utilisant l'index
function searchData(searchTerm) {
  let transaction = db.transaction(["ProductStore"], "readonly");
  let objectStore = transaction.objectStore("ProductStore");
  let index = objectStore.index("name");

  let request = index.getAll(IDBKeyRange.bound(searchTerm, searchTerm + '\uffff'));

  request.onsuccess = function(event) {
    let results = event.target.result;
    console.log("Résultats de la recherche :", results);
  };
}

// Exemple d'utilisation
createSearchIndex();

// Ajouter des données d'exemple
let transaction = db.transaction(["ProductStore"], "readwrite");
let objectStore = transaction.objectStore("ProductStore");
objectStore.add({ id: 1, name: "Pomme", category: "Fruit" });
objectStore.add({ id: 2, name: "Banane", category: "Fruit" });
objectStore.add({ id: 3, name: "Orange", category: "Fruit" });

// Effectuer une recherche
searchData("Pom");

Nous créons un index sur le champ "name" de l'object store "ProductStore" en utilisant la fonction createSearchIndex. Cela permet une recherche efficace basée sur le nom du produit.

La fonction searchData effectue une recherche en utilisant l'index. Elle prend un terme de recherche en entrée et utilise la méthode getAll avec un IDBKeyRange pour trouver tous les produits qui correspondent au terme de recherche.

Dans l'exemple d'utilisation, nous créons l'index de recherche, ajoutons quelques données d'exemple à l'object store "ProductStore", puis effectuons une recherche de produits avec "Pom" dans leur nom. Les résultats de la recherche sont affichés dans la console.

Ce ne sont que quelques exemples de la façon dont IndexedDB peut être utilisé dans des scénarios pratiques. La flexibilité et les fonctionnalités puissantes d'IndexedDB le rendent adapté à un large éventail de cas d'utilisation où le stockage et la manipulation de données côté client sont nécessaires.