Les objets de stockage Web localStorage
et sessionStorage
permettent d’enregistrer les paires clé/valeur dans le navigateur.
Ce qui est intéressant à leur sujet, c’est que les données survivent à une actualisation de la page (pour sessionStorage
) et même à un redémarrage complet du navigateur (pour localStorage
). Nous verrons cela très bientôt.
Nous avons déjà des cookies. Pourquoi des objets supplémentaires ?
- Contrairement aux cookies, les objets de stockage Web ne sont pas envoyés au serveur à chaque requête. Grâce à cela, nous pouvons stocker beaucoup plus. La plupart des navigateurs autorisent au moins 5 mégaoctets de données (ou plus) et ont des paramètres pour configurer cela.
- Contrairement aux cookies également, le serveur ne peut pas manipuler les objets de stockage via les en-têtes HTTP. Tout se fait en JavaScript.
- Le stockage est lié à l’origine (triplet domaine/protocole/port). Autrement dit, différents protocoles ou sous-domaines impliquent différents objets de stockage, ils ne peuvent pas accéder aux données les uns des autres.
Les deux objets de stockage fournissent les mêmes méthodes et propriétés :
setItem(key, value)
– stocke la paire clé/valeur.getItem(key)
– récupère la valeur par clé.removeItem(key)
– supprime la clé avec sa valeur.clear()
– supprime tout.key(index)
– récupère la clé sur une position donnée.length
– le nombre d’éléments stockés.
Comme vous pouvez le voir, c’est comme une collection Map
(setItem/getItem/removeItem
), mais permet également l’accès par index avec key(index)
.
Voyons voir comment ça fonctionne.
Démo localStorage
Les principales caractéristiques de localStorage
sont les suivantes :
- Partagé entre tous les onglets et fenêtres d’une même origine.
- Les données n’expirent pas. Il reste après le redémarrage du navigateur et même le redémarrage du système d’exploitation.
Par exemple, si vous exécutez ce code…
localStorage.setItem('test', 1);
…Et fermez/ouvrez le navigateur ou ouvrez simplement la même page dans une autre fenêtre, alors vous pouvez l’obtenir comme ceci :
alert( localStorage.getItem('test') ); // 1
Il suffit d’être sur la même origine (domaine/port/protocole), le chemin de l’url peut être différent.
Le localStorage
est partagé entre toutes les fenêtres avec la même origine, donc si nous définissons les données dans une fenêtre, le changement devient visible dans une autre.
Accès de type objet
Nous pouvons également utiliser un objet simple pour obtenir/définir des clés, comme ceci :
// définir la clé
localStorage.test = 2;
// obtenir la clé
alert( localStorage.test ); // 2
// supprimer clé
delete localStorage.test;
C’est autorisé pour des raisons historiques, et fonctionne plus ou moins, mais généralement déconseillé, car :
-
Si la clé est générée par l’utilisateur, elle peut être n’importe quoi, comme
length
outoString
, ou une autre méthode intégrée delocalStorage
. Dans ce cas,getItem/setItem
fonctionne correctement, tandis que l’accès de type objet échoue :let key = 'length'; localStorage[key] = 5; // Erreur, impossible d'attribuer 'length'
-
Il y a un événement
storage
, il se déclenche lorsque nous modifions les données. Cet événement ne se produit pas pour un accès de type objet. Nous verrons cela plus loin dans ce chapitre.
Boucle sur les clés
Comme nous l’avons vu, les méthodes fournissent la fonctionnalité “get/set/remove by key”. Mais comment obtenir toutes les valeurs ou clés enregistrées ?
Malheureusement, les objets de stockage ne sont pas itérables.
Une façon consiste à boucler sur eux comme sur un tableau :
for (let i=0; i<localStorage.length; i++) {
let key = localStorage.key(i);
alert(`${key}: ${localStorage.getItem(key)}`);
}
Une autre façon consiste à utiliser la boucle for key in localStorage
, comme nous le faisons avec des objets normaux.
Il itère sur les clés, mais génère également quelques champs intégrés dont nous n’avons pas besoin :
// mauvais essai
for(let key in localStorage) {
alert(key); // affiche getItem, setItem et d'autres éléments intégrés
}
…Nous devons donc soit filtrer les champs du prototype avec la vérification hasOwnProperty
:
for(let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue; // sauter des clés comme "setItem", "getItem" etc.
}
alert(`${key}: ${localStorage.getItem(key)}`);
}
…Ou récupérez simplement les clés “propres” avec Object.keys
, puis bouclez-les si nécessaire :
let keys = Object.keys(localStorage);
for(let key of keys) {
alert(`${key}: ${localStorage.getItem(key)}`);
}
Ce dernier fonctionne, car Object.keys
ne renvoie que les clés appartenant à l’objet, en ignorant le prototype.
Chaînes uniquement
Veuillez noter que la clé et la valeur doivent être des chaînes.
S’il s’agissait d’un autre type, comme un nombre ou un objet, il est automatiquement converti en chaîne de caractères :
localStorage.user = {name: "John"};
alert(localStorage.user); // [object Object]
We can use JSON
to store objects though:
localStorage.user = JSON.stringify({name: "John"});
// un peu plus tard
let user = JSON.parse( localStorage.user );
alert( user.name ); // John
Il est également possible de transformer en chaîne l’ensemble de l’objet de stockage, par ex. à des fins de débogage :
// ajout d'options de formatage à JSON.stringify pour rendre l'objet plus beau
alert( JSON.stringify(localStorage, null, 2) );
sessionStorage
L’objet sessionStorage
est beaucoup moins utilisé que localStorage
.
Les propriétés et les méthodes sont les mêmes, mais c’est beaucoup plus limité :
- Le
sessionStorage
n’existe que dans l’onglet actuel du navigateur.- Un autre onglet avec la même page aura un stockage différent.
- Mais il est partagé entre les iframes du même onglet (en supposant qu’ils proviennent de la même origine).
- Les données survivent à l’actualisation de la page, mais pas à la fermeture/ouverture de l’onglet.
Voyons cela en action.
Exécutez ce code…
sessionStorage.setItem('test', 1);
…Puis actualisez la page. Maintenant, vous pouvez toujours obtenir les données :
alert( sessionStorage.getItem('test') ); // après rafraîchissement : 1
…Mais si vous ouvrez la même page dans un autre onglet et réessayez, le code ci-dessus renvoie null
, ce qui signifie “rien trouvé”.
C’est exactement parce que sessionStorage
est lié non seulement à l’origine, mais également à l’onglet du navigateur. Pour cette raison, sessionStorage
est utilisé avec parcimonie.
Événement de stockage
Lorsque les données sont mises à jour dans localStorage
ou sessionStorage
, l’événement storage se déclenche, avec les propriétés :
key
– la clé qui a été changée (null
si.clear()
est appelé).oldValue
– l’ancienne valeur (null
si la clé vient d’être ajoutée).newValue
– la nouvelle valeur (null
si la clé est supprimée).url
– l’url du document où la mise à jour s’est produite.storageArea
– objetlocalStorage
ousessionStorage
où la mise à jour s’est produite.
L’important est que l’événement se déclenche sur tous les objets window
où le stockage est accessible, sauf celui qui l’a provoqué.
Élaborons.
Imaginez, vous avez deux fenêtres avec le même site dans chacune. Donc localStorage
est partagé entre eux.
Vous pouvez ouvrir cette page dans deux fenêtres de navigateur pour tester le code ci-dessous.
Si les deux fenêtres écoutent window.onstorage
, chacune réagira aux mises à jour qui se sont produites dans l’autre.
// se déclenche sur les mises à jour effectuées sur le même stockage à partir d'autres documents
window.onstorage = (event) => {
// peut également utiliser window.addEventListener('storage', event => {
if (event.key != "now") return;
alert(event.key + ":" + event.newValue + " at " + event.url);
};
localStorage.setItem('now', Date.now());
Veuillez noter que l’événement contient également : event.url
– l’url du document où les données ont été mises à jour.
De plus, event.storageArea
contient l’objet de stockage – l’événement est le même pour sessionStorage
et localStorage
, donc event.storageArea
fait référence à celui qui a été modifié. On peut même vouloir y remettre quelque chose, “répondre” à un changement.
Cela permet à différentes fenêtres d’une même origine d’échanger des messages.
Les navigateurs modernes prennent également en charge Broadcast channel API, l’API spéciale pour la communication inter-fenêtre de même origine, elle est plus complète, mais moins prise en charge. Il existe des bibliothèques qui polyfill cette API, basée sur localStorage
, qui la rendent disponible partout.
Résumé
Les objets de stockage Web localStorage
et sessionStorage
permettent de stocker des paires clé/valeur dans le navigateur.
clé
etvaleur
doivent être des chaînes.- La limite est de 5mb+, dépend du navigateur.
- Ils n’expirent pas.
- Les données sont liées à l’origine (domaine/port/protocole).
localStorage |
sessionStorage |
---|---|
Partagé entre tous les onglets et fenêtres de même origine | Visible dans un onglet de navigateur, y compris les iframes de la même origine |
Survit au redémarrage du navigateur | Survit à l’actualisation de la page (mais pas à la fermeture de l’onglet) |
API :
setItem(key, value)
– stocke la paire clé/valeur.getItem(key)
– récupère la valeur par clé.removeItem(key)
– supprime la clé avec sa valeur.clear()
– supprime tout.key(index)
– récupère la clé sur une position donnée.length
– le nombre d’éléments stockés.- Utilisez
Object.keys
pour obtenir toutes les clés. - Nous accédons aux clés en tant que propriétés d’objet, dans ce cas l’événement
storage
n’est pas déclenché.
Événement de stockage :
- Se déclenche sur les appels
setItem
,removeItem
,clear
. - Contient toutes les données sur l’opération (
key/oldValue/newValue
), le documenturl
et l’objet de stockagestorageArea
. - Se déclenche sur tous les objets
window
qui ont accès au stockage sauf celui qui l’a généré (dans un onglet poursessionStorage
, globalement pourlocalStorage
).