Stockage coté client avec IndexedDB

Javascript
Jérémie Loscos - 10/03/2018 à 00:00:000 commentaire

Une application web peut avoir besoin d'enregistrer des informations en local dans le navigateur. Ça peut être pour enregistrer des informations de navigation, des paramètres utilisateur, des brouillons, ... Il y a beaucoup de cas d'utilisations où on peut vouloir enregistrer une information qui n'a de sens que pour un utilisateur donné, il est plus adapté dans ce cas de l'enregistrer coté client, c'est à dire dans le navigateur de l'utilisateur.


On a vu dans un post précédent comment utiliser le HTML 5 Application Cache pour rendre un site accessible hors ligne. Ce cache est pratique pour enregistrer des ressources statiques, mais quand il s'agit de ressources dynamiques il vaut mieux gérer soit même la logique de stockage. On peut par exemple vouloir stocker des informations saisies par l'utilisateur qui seront envoyées au serveur lorsque l'utilisateur retrouvera sa connexion.


Pour stocker des données sur le navigateur du client on a plusieurs manières de faire


-Les cookies, mais la place est très limités et les cookies c'est vraiment pas fait pour ça

-Le local/session storage. C'est un peu mieux mais on y accède de manière synchrone et ça ne stock que des couples clé/valeur. Ce qui n'est pas adapté quand veut stocker des données complexes

-La base WebSQL qui est déprécié, n'est pas supporté par IE ou Edge et ne le sera jamais.


La meilleur solution est l'IndexedDB.


C'est une base de données, qui est plus adaptée que le local storage à stocker beaucoup de données. Elle s'interroge de manière asynchrone ce qui fait que son utilisation ne provoque pas de freeze dans l'interface graphique.

IndexedDB est une base de données noSQL orientée pairs clé valeur, qui permet de stocker des données dans le navigateur de l'utilisateur. Les données stockées dans cette base sont des objets javascript.


L’IndexedDB est composée de plusieurs concepts :

  • Database: c'est l'élément racine qu'on manipule. Les bases de données sont spécifiques à une origine. Un script s'exécutant sur une page de toto.com ne peut pas accéder à la base de données d'un script s'exécutant sur titi.com
  • Store: C'est l'élément dans lequel on va stocker des objets javascript. C'est l'équivalent d'une table dans une base de données classique. Généralement les objets qu'on met dans un store sont du même "type", mais ces objets n'ont pas nécessairement les même propriétés
  • Cursor: Nous permet de parcourir un jeu de données
  • Transaction: C’est au travers des transactions qu’on manipule les données de cette base.
  • Index: Permet d'organiser les données d'un store selon une propriété de ses objets.

  

L'API de IndexedDB utilise principalement des fonctions de callback. Pour que ce soit simple à utiliser, il vaut mieux encapsuler ces appels dans des Promise. Les exemples suivant sont en Typescript.


Ouvrir une base :

code

Lors de l’ouverture de la base, si la base n’existe pas (ou n’est pas à jour) la fonction de callback onupgradeneeded est appelée. C’est dans cette fonction qu’il faut créer notre structure de stores et d’indexes. Si notre application évolue et que la structure change, c’est dans cette fonction qu’on gérerait la migration.

 


Créer un store :

code

 

Quand on crée un store, on peut préciser avec le paramètre keyPath quelle propriété des objets javascript qu’on va y mettre servira de clé primaire. On peut aussi créer un ou plusieurs indexes sur les propriétés des objets qu’on met dans le store. A la différence du keyPath, un index n’est pas forcément unique.

 


Modifier une valeur :

 

code

 

Pour manipuler les données d’une base indexeddb, il faut commencer par créer une transaction en mode lecture/écriture, à partir de cette transaction on peut récupérer un store par son nom, et sur l’objet store, la méthode put nous permet d’ajouter/remplacer la valeur associée à une clé.

Le fait qu’on ai précisé la clé primaire lors de la création de notre store fait qu’on n’a pas besoin d’indiquer la clé à laquelle sont associés les objets stockés.

 

Exemple d’utilisation :



Lire une valeur :

 

Quand on veut lire une valeur, le principe est le même que pour l’écriture, on crée une transaction, on récupère le store et on utilise la méthode get pour récupérer la valeur associée à une clé.

code

 

 

Requetes :

 

Comme cette base de données est indexée, on peut facilement faire une recherche basée sur la clé ou sur un index. Pour cela on utilise l’objet IDBKeyRange avec lequel on indique les bornes inférieures et supérieurs de l’ensemble de clé qu’on cherche.

code

Pour lire plusieurs données dans la base, il faut faire un cursor. L’événement onsuccess est appelé pour chaque valeur renvoyée par la base, et le cursor nous permet de récupérer cette valeur et d’aller chercher la suivante.

 

 


Indexes :

 

Jusque-là on a vu comment récupérer les données par leur clé primaire, mais on peut aussi les chercher par un index. Pour cela on indique d’abord sur quel index on veut chercher les données du store. Un index n’est pas forcément unique, on peut avoir plusieurs valeurs associées à une clé. Comme avec le store, si on veut lire plusieurs valeurs on passe par un cursor. La méthode openCursor peut prendre en paramètre une clé ou un objet IDBKeyRange.

 

 

code

 

 

La base IndexedDB est plus pratique et plus performante que le local storage et elle est compatible avec tous les navigateurs depuis IE 10. Son principal inconvénient est que l’utilisation des fonctions de callback peut être un peu lourde à mettre en place, mais comme on vient de voir, il est assez simple d’encapsuler ces callbacks dans des Promises pour utiliser facilement cette base.

 

Code complet des exemples sur https://github.com/jloscos/indexeddb-promise-exemple

 

Commentaires :

Aucun commentaires pour le moment


Laissez un commentaire :

Réalisé par
Expaceo