Persistenz von Daten über das Neuladen von Seiten hinweg: Cookies, IndexedDB und alles dazwischen

Veröffentlicht: 2022-03-11

Angenommen, ich besuche eine Website. Ich klicke mit der rechten Maustaste auf einen der Navigationslinks und wähle aus, den Link in einem neuen Fenster zu öffnen. Was soll passieren? Wenn ich wie die meisten Benutzer bin, erwarte ich, dass die neue Seite den gleichen Inhalt hat, als hätte ich direkt auf den Link geklickt. Der einzige Unterschied sollte sein, dass die Seite in einem neuen Fenster erscheint. Wenn Ihre Website jedoch eine Single-Page-Anwendung (SPA) ist, sehen Sie möglicherweise seltsame Ergebnisse, es sei denn, Sie haben diesen Fall sorgfältig geplant.

Denken Sie daran, dass in einer SPA ein typischer Navigationslink oft eine Fragmentkennung ist, die mit einem Rautezeichen (#) beginnt. Beim direkten Klick auf den Link wird die Seite nicht neu geladen, sodass alle in JavaScript-Variablen gespeicherten Daten erhalten bleiben. Aber wenn ich den Link in einem neuen Tab oder Fenster öffne, lädt der Browser die Seite neu und initialisiert alle JavaScript-Variablen neu. Daher werden alle HTML-Elemente, die an diese Variablen gebunden sind, anders angezeigt, es sei denn, Sie haben Schritte unternommen, um diese Daten irgendwie zu erhalten.

Persistenz von Daten über das Neuladen von Seiten hinweg: Cookies, IndexedDB und alles dazwischen

Persistenz von Daten über das Neuladen von Seiten hinweg: Cookies, IndexedDB und alles dazwischen
Twittern

Es gibt ein ähnliches Problem, wenn ich die Seite explizit neu lade, z. B. durch Drücken von F5. Sie denken vielleicht, ich sollte niemals F5 drücken müssen, weil Sie einen Mechanismus eingerichtet haben, um Änderungen automatisch vom Server zu übertragen. Aber wenn ich ein typischer Benutzer bin, können Sie darauf wetten, dass ich die Seite trotzdem neu lade. Vielleicht scheint mein Browser den Bildschirm falsch neu gezeichnet zu haben, oder ich möchte einfach sicher sein, dass ich die allerneuesten Aktienkurse habe.

APIs können zustandslos sein, menschliche Interaktion ist es nicht

Im Gegensatz zu einer internen Anfrage über eine RESTful-API ist die Interaktion eines menschlichen Benutzers mit einer Website nicht zustandslos. Als Webnutzer betrachte ich meinen Besuch auf Ihrer Website als Sitzung, fast wie einen Telefonanruf. Ich erwarte, dass sich der Browser Daten über meine Sitzung merkt, genauso wie ich erwarte, dass sich der Mitarbeiter bei einem Anruf bei Ihrer Vertriebs- oder Support-Hotline daran erinnert, was zuvor im Anruf gesagt wurde.

Ein naheliegendes Beispiel für Sitzungsdaten ist, ob ich angemeldet bin und wenn ja, als welcher Benutzer. Sobald ich durch einen Anmeldebildschirm gehe, sollte ich in der Lage sein, frei durch die benutzerspezifischen Seiten der Website zu navigieren. Wenn ich einen Link in einem neuen Tab oder Fenster öffne und mir ein anderer Anmeldebildschirm angezeigt wird, ist das nicht sehr benutzerfreundlich.

Ein weiteres Beispiel ist der Inhalt des Einkaufswagens auf einer E-Commerce-Site. Wenn das Drücken von F5 den Einkaufswagen leert, werden die Benutzer wahrscheinlich verärgert sein.

In einer herkömmlichen mehrseitigen Anwendung, die in PHP geschrieben ist, würden Sitzungsdaten im superglobalen Array $_SESSION gespeichert. Aber in einem SPA muss es irgendwo auf der Client-Seite sein. Es gibt vier Hauptoptionen zum Speichern von Sitzungsdaten in einem SPA:

  • Kekse
  • Fragmentkennung
  • Webspeicher
  • IndexedDB

Vier Kilobyte Cookies

Cookies sind eine ältere Form der Webspeicherung im Browser. Sie waren ursprünglich dazu gedacht, vom Server empfangene Daten in einer Anfrage zu speichern und sie in nachfolgenden Anfragen an den Server zurückzusenden. Aber von JavaScript aus können Sie Cookies verwenden, um nahezu jede Art von Daten zu speichern, bis zu einer Größenbeschränkung von 4 KB pro Cookie. AngularJS bietet das Modul ngCookies zur Verwaltung von Cookies an. Es gibt auch ein js-cookies-Paket, das ähnliche Funktionen in jedem Framework bereitstellt.

Denken Sie daran, dass jedes von Ihnen erstellte Cookie bei jeder Anfrage an den Server gesendet wird, unabhängig davon, ob es sich um ein erneutes Laden der Seite oder eine Ajax-Anfrage handelt. Aber wenn die Hauptsitzungsdaten, die Sie speichern müssen, das Zugriffstoken für den angemeldeten Benutzer sind, möchten Sie, dass dieses sowieso bei jeder Anfrage an den Server gesendet wird. Es liegt auf der Hand, diese automatische Cookie-Übertragung als Standardmittel zur Angabe des Zugriffstokens für Ajax-Anforderungen zu verwenden.

Sie können argumentieren, dass die Verwendung von Cookies auf diese Weise mit der RESTful-Architektur nicht kompatibel ist. Aber in diesem Fall ist es in Ordnung, da jede Anfrage über die API immer noch zustandslos ist und einige Eingaben und einige Ausgaben hat. Es ist nur so, dass eine der Eingaben auf komische Weise über ein Cookie gesendet wird. Wenn Sie dafür sorgen können, dass die Anmelde-API-Anforderung das Zugriffstoken auch in einem Cookie zurücksendet, muss Ihr clientseitiger Code kaum mit Cookies umgehen. Auch hier handelt es sich nur um eine weitere Ausgabe der Anfrage, die auf ungewöhnliche Weise zurückgegeben wird.

Cookies bieten einen Vorteil gegenüber Webspeicherung. Sie können im Anmeldeformular ein Kontrollkästchen „Angemeldet bleiben“ aktivieren. Mit der Semantik erwarte ich, dass ich, wenn ich es deaktiviert lasse, angemeldet bleibe, wenn ich die Seite neu lade oder einen Link in einem neuen Tab oder Fenster öffne, aber ich werde garantiert abgemeldet, sobald ich den Browser schließe. Dies ist eine wichtige Sicherheitsfunktion, wenn ich einen gemeinsam genutzten Computer verwende. Wie wir später sehen werden, unterstützt der Webspeicher dieses Verhalten nicht.

Wie könnte dieser Ansatz in der Praxis funktionieren? Angenommen, Sie verwenden LoopBack auf der Serverseite. Sie haben ein Personenmodell definiert, indem Sie das integrierte Benutzermodell erweitert und die Eigenschaften hinzugefügt haben, die Sie für jeden Benutzer verwalten möchten. Sie haben das Personenmodell so konfiguriert, dass es über REST verfügbar gemacht wird. Jetzt müssen Sie server/server.js anpassen, um das gewünschte Cookie-Verhalten zu erreichen. Unten ist server/server.js, beginnend mit dem, was von slc loopback generiert wurde, mit den markierten Änderungen:

 var loopback = require('loopback'); var boot = require('loopback-boot'); var app = module.exports = loopback(); app.start = function() { // start the web server return app.listen(function() { app.emit('started'); var baseUrl = app.get('url').replace(/\/$/, ''); console.log('Web server listening at: %s', baseUrl); if (app.get('loopback-component-explorer')) { var explorerPath = app.get('loopback-component-explorer').mountPath; console.log('Browse your REST API at %s%s', baseUrl, explorerPath); } }); }; // start of first change app.use(loopback.cookieParser('secret')); // end of first change // Bootstrap the application, configure models, datasources and middleware. // Sub-apps like REST API are mounted via boot scripts. boot(app, __dirname, function(err) { if (err) throw err; // start of second change app.remotes().after('Person.login', function (ctx, next) { if (ctx.result.id) { var opts = {signed: true}; if (ctx.req.body.rememberme !== false) { opts.maxAge = 1209600000; } ctx.res.cookie('authorization', ctx.result.id, opts); } next(); }); app.remotes().after('Person.logout', function (ctx, next) { ctx.res.cookie('authorization', ''); next(); }); // end of second change // start the server if `$ node server.js` if (require.main === module) app.start(); });

Die erste Änderung konfiguriert den Cookie-Parser so, dass er „geheim“ als Cookie-Signaturgeheimnis verwendet, wodurch signierte Cookies aktiviert werden. Sie müssen dies tun, da LoopBack zwar nach einem Zugriffstoken in einem der Cookies „authorization“ oder „access_token“ sucht, es jedoch erfordert, dass ein solches Cookie signiert ist. Eigentlich ist diese Forderung sinnlos. Durch das Signieren eines Cookies soll sichergestellt werden, dass das Cookie nicht verändert wurde. Es besteht jedoch keine Gefahr, dass Sie das Zugriffstoken ändern. Schließlich hätten Sie das Zugriffstoken in unsignierter Form als gewöhnlichen Parameter senden können. Sie müssen sich also keine Sorgen machen, dass das Cookie-Signaturgeheimnis schwer zu erraten ist, es sei denn, Sie verwenden signierte Cookies für etwas anderes.

Die zweite Änderung richtet eine Nachbearbeitung für die Methoden Person.login und Person.logout ein. Für Person.login möchten Sie das resultierende Zugriffstoken nehmen und es auch als signierte Cookie-„Autorisierung“ an den Client senden. Der Client kann dem Parameter "credentials" eine weitere Eigenschaft hinzufügen, "rememberme", die angibt, ob das Cookie für 2 Wochen persistent gemacht werden soll. Die Voreinstellung ist wahr. Die Anmeldemethode selbst wird diese Eigenschaft ignorieren, aber der Postprozessor wird sie überprüfen.

Für Person.logout möchten Sie dieses Cookie löschen.

Sie können die Ergebnisse dieser Änderungen sofort im StrongLoop API Explorer sehen. Normalerweise müssten Sie nach einer Person.login-Anforderung das Zugriffstoken kopieren, in das Formular oben rechts einfügen und auf Zugriffstoken festlegen klicken. Aber mit diesen Änderungen müssen Sie nichts davon tun. Das Zugriffstoken wird automatisch als Cookie-„Autorisierung“ gespeichert und bei jeder nachfolgenden Anfrage zurückgesendet. Wenn der Explorer die Response-Header von Person.login anzeigt, lässt er das Cookie weg, da JavaScript niemals Set-Cookie-Header sehen darf. Aber seien Sie versichert, der Keks ist da.

Auf der Client-Seite würden Sie beim Neuladen der Seite sehen, ob die Cookie-'Autorisierung' vorhanden ist. Wenn dies der Fall ist, müssen Sie Ihren Datensatz der aktuellen Benutzer-ID aktualisieren. Der wahrscheinlich einfachste Weg, dies zu tun, besteht darin, die Benutzer-ID bei erfolgreicher Anmeldung in einem separaten Cookie zu speichern, damit Sie sie beim erneuten Laden der Seite abrufen können.

Die Fragmentkennung

Wenn ich eine Website besuche, die als SPA implementiert wurde, sieht die URL in der Adressleiste meines Browsers möglicherweise so aus: „https://example.com/#/my-photos/37“. Der Fragment-Identifikator-Teil davon, „#/my-photos/37“, ist bereits eine Sammlung von Zustandsinformationen, die als Sitzungsdaten angesehen werden könnten. In diesem Fall sehe ich mir wahrscheinlich eines meiner Fotos an, das mit der ID 37.

Sie können entscheiden, andere Sitzungsdaten in die Fragmentkennung einzubetten. Erinnern Sie sich daran, dass Sie im vorherigen Abschnitt mit dem in der Cookie-„Autorisierung“ gespeicherten Zugriffstoken immer noch irgendwie die userId im Auge behalten mussten. Eine Möglichkeit besteht darin, es in einem separaten Cookie zu speichern. Ein anderer Ansatz besteht jedoch darin, es in die Fragmentkennung einzubetten. Sie könnten festlegen, dass alle Seiten, die ich besuche, eine Fragmentkennung haben, die mit „#/u/XXX“ beginnt, während XXX die Benutzer-ID ist, während ich angemeldet bin. Im vorherigen Beispiel könnte die Fragmentkennung also „#/u/59/my-photos/37“ lauten, wenn meine Benutzer-ID 59 ist.

Theoretisch könnten Sie das Zugriffstoken selbst in die Fragmentkennung einbetten, wodurch Cookies oder Webspeicherung überflüssig werden. Aber das wäre eine schlechte Idee. Mein Zugriffstoken wäre dann in der Adressleiste sichtbar. Jeder, der mir mit einer Kamera über die Schulter schaut, könnte einen Schnappschuss des Bildschirms machen und sich so Zugang zu meinem Konto verschaffen.

Ein letzter Hinweis: Es ist möglich, eine SPA so einzurichten, dass sie überhaupt keine Fragmentkennungen verwendet. Stattdessen werden gewöhnliche URLs wie „http://example.com/app/dashboard“ und „http://example.com/app/my-photos/37“ verwendet, wobei der Server so konfiguriert ist, dass er den HTML-Code der obersten Ebene für Sie zurückgibt SPA als Antwort auf eine Anfrage für eine dieser URLs. Ihr SPA führt dann sein Routing basierend auf dem Pfad (z. B. „/app/dashboard“ oder „/app/my-photos/37“) anstelle der Fragmentkennung durch. Es fängt Klicks auf Navigationslinks ab und verwendet History.pushState() , um die neue URL zu pushen, und fährt dann wie gewohnt mit dem Routing fort. Es wartet auch auf Popstate-Ereignisse, um zu erkennen, dass der Benutzer auf die Schaltfläche „Zurück“ klickt, und fährt erneut mit dem Routing auf der wiederhergestellten URL fort. Die vollständigen Details, wie dies implementiert wird, würden den Rahmen dieses Artikels sprengen. Aber wenn Sie diese Technik verwenden, können Sie natürlich Sitzungsdaten im Pfad anstelle der Fragmentkennung speichern.

Webspeicher

Web Storage ist ein Mechanismus für JavaScript, um Daten im Browser zu speichern. Wie Cookies ist der Webspeicher für jeden Ursprung separat. Jedes gespeicherte Element hat einen Namen und einen Wert, die beide Zeichenfolgen sind. Der Webspeicher ist jedoch für den Server völlig unsichtbar und bietet eine viel größere Speicherkapazität als Cookies. Es gibt zwei Arten von Webspeicher: lokaler Speicher und Sitzungsspeicher.

Ein Element des lokalen Speichers ist auf allen Registerkarten aller Fenster sichtbar und bleibt auch nach dem Schließen des Browsers bestehen. Insofern verhält es sich ähnlich wie ein Cookie mit einem sehr weit in der Zukunft liegenden Verfallsdatum. Daher eignet es sich zum Speichern eines Zugriffstokens für den Fall, dass der Benutzer im Anmeldeformular „angemeldet bleiben“ aktiviert hat.

Ein Sitzungsspeicherelement ist nur auf der Registerkarte sichtbar, auf der es erstellt wurde, und verschwindet, wenn diese Registerkarte geschlossen wird. Dadurch unterscheidet sich seine Lebensdauer stark von der eines Cookies. Denken Sie daran, dass ein Sitzungscookie immer noch auf allen Registerkarten aller Fenster sichtbar ist.

Wenn Sie das AngularJS SDK für LoopBack verwenden, verwendet die Clientseite automatisch den Webspeicher, um sowohl das Zugriffstoken als auch die Benutzer-ID zu speichern. Dies geschieht im LoopBackAuth-Dienst in js/services/lb-services.js. Es wird der lokale Speicher verwendet, es sei denn, der Parameter „rememberMe“ ist falsch (was normalerweise bedeutet, dass das Kontrollkästchen „angemeldet bleiben“ deaktiviert war). In diesem Fall wird der Sitzungsspeicher verwendet.

Das Ergebnis ist, dass wenn ich mich mit deaktiviertem „Angemeldet bleiben“ anmelde und dann einen Link in einem neuen Tab oder Fenster öffne, werde ich dort nicht angemeldet. Höchstwahrscheinlich werde ich den Anmeldebildschirm sehen. Sie können selbst entscheiden, ob dies ein akzeptables Verhalten ist. Einige mögen es für eine nette Funktion halten, bei der Sie mehrere Registerkarten haben können, von denen jede als ein anderer Benutzer angemeldet ist. Oder Sie entscheiden sich vielleicht dafür, dass kaum jemand mehr gemeinsam genutzte Computer verwendet, sodass Sie das Kontrollkästchen „Angemeldet bleiben“ einfach ganz weglassen können.

Wie würde also die Behandlung der Sitzungsdaten aussehen, wenn Sie sich für das AngularJS SDK für LoopBack entscheiden? Angenommen, Sie haben die gleiche Situation wie zuvor auf der Serverseite: Sie haben ein Personenmodell definiert, das Benutzermodell erweitert, und Sie haben das Personenmodell über REST verfügbar gemacht. Sie werden keine Cookies verwenden, daher müssen Sie keine der zuvor beschriebenen Änderungen vornehmen.

Auf der Client-Seite, irgendwo in Ihrem äußersten Controller, haben Sie wahrscheinlich eine Variable wie $scope.currentUserId, die die Benutzer-ID des aktuell angemeldeten Benutzers enthält, oder null, wenn der Benutzer nicht angemeldet ist. Dann müssen Sie das Neuladen der Seite richtig handhaben Fügen Sie einfach diese Anweisung in die Konstruktorfunktion für diesen Controller ein:

 $scope.currentUserId = Person.getCurrentId();

So einfach ist das. Fügen Sie „Person“ als Abhängigkeit Ihres Controllers hinzu, falls dies noch nicht geschehen ist.

IndexedDB

IndexedDB ist eine neuere Einrichtung zum Speichern großer Datenmengen im Browser. Sie können es verwenden, um Daten eines beliebigen JavaScript-Typs zu speichern, z. B. ein Objekt oder ein Array, ohne sie serialisieren zu müssen. Alle Anfragen an die Datenbank sind asynchron, sodass Sie einen Rückruf erhalten, wenn die Anfrage abgeschlossen ist.

Sie können IndexedDB verwenden, um strukturierte Daten zu speichern, die nichts mit Daten auf dem Server zu tun haben. Ein Beispiel könnte ein Kalender, eine Aufgabenliste oder gespeicherte Spiele sein, die lokal gespielt werden. In diesem Fall handelt es sich um eine wirklich lokale Anwendung, und Ihre Website ist nur das Vehikel für die Bereitstellung.

Derzeit unterstützen Internet Explorer und Safari IndexedDB nur teilweise. Andere große Browser unterstützen es vollständig. Eine ernsthafte Einschränkung besteht derzeit jedoch darin, dass Firefox IndexedDB im privaten Browsermodus vollständig deaktiviert.

Als konkretes Beispiel für die Verwendung von IndexedDB nehmen wir die Schiebepuzzle-Anwendung von Pavol Daniš und optimieren sie so, dass der Zustand des ersten Puzzles, des einfachen 3x3-Schiebepuzzles basierend auf dem AngularJS-Logo, nach jedem Zug gespeichert wird. Ein erneutes Laden der Seite stellt dann den Zustand dieses ersten Rätsels wieder her.

Ich habe einen Fork des Repositorys mit diesen Änderungen eingerichtet, die sich alle in app/js/puzzle/slidingPuzzle.js befinden. Wie Sie sehen können, ist selbst eine rudimentäre Verwendung von IndexedDB ziemlich aufwendig. Ich zeige nur die Highlights unten. Zuerst wird die Funktion restore während des Ladens der Seite aufgerufen, um die IndexedDB-Datenbank zu öffnen:

 /* * Tries to restore game */ this.restore = function(scope, storekey) { this.storekey = storekey; if (this.db) { this.restore2(scope); } else if (!window.indexedDB) { console.log('SlidingPuzzle: browser does not support indexedDB'); this.shuffle(); } else { var self = this; var request = window.indexedDB.open('SlidingPuzzleDatabase'); request.onerror = function(event) { console.log('SlidingPuzzle: error opening database, ' + request.error.name); scope.$apply(function() { self.shuffle(); }); }; request.onupgradeneeded = function(event) { event.target.result.createObjectStore('SlidingPuzzleStore'); }; request.onsuccess = function(event) { self.db = event.target.result; self.restore2(scope); }; } };

Das Ereignis „request.onupgradeneeded“ behandelt den Fall, dass die Datenbank noch nicht existiert. In diesem Fall erstellen wir den Objektspeicher.

Sobald die Datenbank geöffnet ist, wird die Funktion restore2 aufgerufen, die nach einem Datensatz mit einem bestimmten Schlüssel sucht (der in diesem Fall tatsächlich die Konstante 'Basic' ist):

 /* * Tries to restore game, once database has been opened */ this.restore2 = function(scope) { var transaction = this.db.transaction('SlidingPuzzleStore'); var objectStore = transaction.objectStore('SlidingPuzzleStore'); var self = this; var request = objectStore.get(this.storekey); request.onerror = function(event) { console.log('SlidingPuzzle: error reading from database, ' + request.error.name); scope.$apply(function() { self.shuffle(); }); }; request.onsuccess = function(event) { if (!request.result) { console.log('SlidingPuzzle: no saved game for ' + self.storekey); scope.$apply(function() { self.shuffle(); }); } else { scope.$apply(function() { self.grid = request.result; }); } }; }

Wenn ein solcher Datensatz existiert, ersetzt sein Wert das Gitterfeld des Puzzles. Wenn beim Wiederherstellen des Spiels ein Fehler auftritt, mischen wir die Kacheln einfach wie zuvor. Beachten Sie, dass das Raster ein 3x3-Array von Kachelobjekten ist, von denen jedes ziemlich komplex ist. Der große Vorteil von IndexedDB besteht darin, dass Sie solche Werte speichern und abrufen können, ohne sie serialisieren zu müssen.

Wir verwenden $apply , um AngularJS darüber zu informieren, dass das Modell geändert wurde, sodass die Ansicht entsprechend aktualisiert wird. Dies liegt daran, dass die Aktualisierung innerhalb eines DOM-Ereignishandlers erfolgt, sodass AngularJS die Änderung sonst nicht erkennen könnte. Jede AngularJS-Anwendung, die IndexedDB verwendet, muss aus diesem Grund wahrscheinlich $apply verwenden.

Nach jeder Aktion, die das Grid-Array ändern würde, wie z. B. eine Verschiebung durch den Benutzer, wird die Funktion save aufgerufen, die den Datensatz basierend auf dem aktualisierten Grid-Wert mit dem entsprechenden Schlüssel hinzufügt oder aktualisiert:

 /* * Tries to save game */ this.save = function() { if (!this.db) { return; } var transaction = this.db.transaction('SlidingPuzzleStore', 'readwrite'); var objectStore = transaction.objectStore('SlidingPuzzleStore'); var request = objectStore.put(this.grid, this.storekey); request.onerror = function(event) { console.log('SlidingPuzzle: error writing to database, ' + request.error.name); }; request.onsuccess = function(event) { // successful, no further action needed }; }

Die verbleibenden Änderungen sollen die obigen Funktionen zu geeigneten Zeiten aufrufen. Sie können den Commit mit allen Änderungen überprüfen. Beachten Sie, dass wir Wiederherstellung nur für das Grundrätsel aufrufen, nicht für die drei fortgeschrittenen Rätsel. Wir nutzen die Tatsache aus, dass die drei fortgeschrittenen Rätsel ein API-Attribut haben, also machen wir für diese einfach das normale Mischen.

Was wäre, wenn wir auch die erweiterten Rätsel speichern und wiederherstellen wollten? Das würde einige Umstrukturierungen erfordern. Bei jedem der erweiterten Puzzles kann der Benutzer die Bildquelldatei und die Puzzledimensionen anpassen. Wir müssten also den in IndexedDB gespeicherten Wert erweitern, um diese Informationen einzubeziehen. Noch wichtiger ist, dass wir eine Möglichkeit benötigen, sie von einer Wiederherstellung aus zu aktualisieren. Das ist ein bisschen viel für dieses schon lange Beispiel.

Fazit

In den meisten Fällen ist Webspeicher die beste Wahl zum Speichern von Sitzungsdaten. Es wird von allen gängigen Browsern vollständig unterstützt und bietet eine viel größere Speicherkapazität als Cookies.

Sie würden Cookies verwenden, wenn Ihr Server bereits so eingerichtet ist, dass sie verwendet werden, oder wenn Sie auf die Daten über alle Registerkarten aller Fenster zugreifen müssen, aber auch sicherstellen möchten, dass sie gelöscht werden, wenn der Browser geschlossen wird.

Sie verwenden die Fragmentkennung bereits, um Sitzungsdaten zu speichern, die für diese Seite spezifisch sind, wie z. B. die ID des Fotos, das sich der Benutzer ansieht. Sie könnten zwar andere Sitzungsdaten in die Fragmentkennung einbetten, dies bietet jedoch keinen wirklichen Vorteil gegenüber Webspeicher oder Cookies.

Die Verwendung von IndexedDB erfordert wahrscheinlich viel mehr Codierung als alle anderen Techniken. Aber wenn die Werte, die Sie speichern, komplexe JavaScript-Objekte sind, die schwierig zu serialisieren wären, oder wenn Sie ein Transaktionsmodell benötigen, kann es sich lohnen.