SlashDB And LocalStorage – Feature Image

Storing information locally within modern browsers local or session storage facilities is a great strategy for assuring that data is available in the case when users are offline (not connected to the Internet) and still want to use back-end data that you can locally cache.

The usual way that developers have stored data given the web’s stateless HTTP transport layer has been via cookies. But cookies have restrictions, as seen below, that you will want to avoid. This is especially true when the data is expanded enough to require the storing in a backend relational database management system. This data can then be accessed via SlashDB through Restful API calls.

Cookie limitations include:

  • Cookies only allow for 4KB of storage
  • Through browser preferences/configuration, users can block first and third party cookies
  • Cookies have a bad rap these days as advertising networks are dropping third party cookies in proliferation. Cookies enable servers to aggregate requests—and thus data—around a particular user.
  • Cookies can add to the load of the page from that domain

Intorducing Web Storage

With web storage, web applications can store data locally within the user’s browser.

Using browser’s localStorage object can help you cut down on requests for database data especially as users go from page to page on your website. You can think of local storage as a data cache that has a 5MB storage limit. Security concerns are similar to any other concerns that would be found around sessions and cookies in any language.

<script>
  localStorage.setItem("BillingCountry", "Brazil");
  sessionStorage.setItem("BillingPostalCode", "12202-9293");
</script>

The localStorage object has convenient getItem and setItem methods that make it a cinch to work with the browser’s local storage and persist data from session to session. This means that once the session (domain / origin) is accessed again in the browser, the user doesn’t even have to be connected to the Internet to use the application, in cases where the server-side relational data does not have to be immediately refreshed.

And you can use sessionStorage instead of localStorage if you want the data to be maintained and associated to the origin (your domain) only until the browser window is closed.

Backend of SlashDB Comes to the Frontend

Using HTTP Restful API calls via SlashDB and continuously writing the response data to the local or session storage is easy to do and allows for uninterrupted application use if your users experience Internet connectivity problems or simply wish to work offline with SlashDB-sourced data (e.g. when flying in a plane). All that needs to be done is a modification of the localStorage object in Javascript.

What follows is a full example that you can quickly experiment with and alter for implementing in your SlashDB-enabled web-based application.

With SlashDB’s Data Discovery feature it’s a cinch to browse through available data tables, filter down to specific columns in such a way as to enumerate an entire vector of records:

The advantages are simplicity from a programmer’s point of view in that the API author needs to know a limited amount about the data schema. Accessing data vectors via SlashDB can be compared to a bucket where you thrown anything you want into it, simply by placing a tag on it.

When you wish to narrow down to the specific record use SlashDB’s Data Discovery feature to visually vector in to that record.

For example, find a scalar for a specific record in the Customer table (i.e. CustomerID: 10), exposing the Email address is as easy as drilling through visual representations of the base table structure to arrive at that scalar:

First:

https://demo.slashdb.com/db/Chinook/Customer

Then, with one click to the individual record:

https://demo.slashdb.com/db/Chinook/Customer/CustomerId/10.html

And finally with a next click, exposing specific column (Email) of that record:

https://demo.slashdb.com/db/Chinook/Customer/CustomerId/10/Email

Corresponding API endpoints in JSON, CSV and XML are made available for programs to consume as can be seen in this addition of  dot json (.json) to the tail end of the URL:

Pulling remote table data into localStorage

Our demo SlashDB instance has implemented an API for a sample Chinook database model.  Details of this relational database example project can be found at https://github.com/lerocha/chinook-database. The Chinook data model represents a digital media store (e.g. iTunes), including tables for Customers as in the example below where we do a full table scan for their Email addresses.

In the example code shown below, we made an HTTP API call via SlashDB and asked for each of the Email addresses from the sample Chinook database. This was done with a JSON formatted response using this URL: http://demo.slashdb.com/db/Chinook/Customer/Email.json

The same storage techniques (setItem/getItem) are then used on the individual column data returned via SlashDB to store/retrieve this data as key/value pairs.

The code below does these three things:

  1. Pulls JSON data from SlashDB API (list of emails) using XHR
  2. Stores each item in browser’s localStorage using setItem
  3. Iterates over emails in localStorage, appending each to the document for display using getItem
<!DOCTYPE html>
<html>
<body>
<div id="result"></div>
<script>
var SlashDBrequest = new XMLHttpRequest();
        // note that the "async" boolean parameter of the open method is false in order to
       // NOT perform the operation asynchronously
             SlashDBrequest.open("GET","http://demo.slashdb.com/db/Chinook/Customer/Email.json",false);        
     SlashDBrequest.setRequestHeader("Content-Type", "text/xml");
     SlashDBrequest.addEventListener("load", function() {
     console.log( SlashDBrequest.response);
     }, false);
     try { 
// when 'offline' don't run the send method
         SlashDBrequest.send();
         } catch (error) {
// do nothing
         }
     if (SlashDBrequest.response !== "") {
       var obj = JSON.parse(SlashDBrequest.response);
       // obj is an array of email addresses parsed from the JSON response
       console.log( obj);
       console.log( obj.length);
       var numberOfEmails = obj.length;
       for (var i = 0; i < numberOfEmails; i++) {
           var EmailAddress = obj[i];
           console.log(EmailAddress);
           if (typeof(Storage) !== "undefined") {
              // Store each of the Email addressed into a key/value pair in the local storage
             localStorage.setItem("Email"+i, EmailAddress);
             } else {
             document.getElementById("result").innerHTML = "Sorry, your browser does not support Local Storage...";
             }
            }//for loop
            localStorage.setItem("savedNumberOfEmails", numberOfEmails );
            //use the array length saved in the local Storage
            }// response is available above
          console.log("Getting all Email items from the local storage for display in DIVs")
          localSavedNumberOfEmails = localStorage.getItem("savedNumberOfEmails");
          var html='';
          for (var i = 0; i <= localSavedNumberOfEmails - 1; i++) {
             html += '<div>' + localStorage.getItem("Email" + i); + '</div>';
             }
          document.getElementById('result').innerHTML += html;
         </script>
       </body>
</html>

When viewed in Safari through the Web Inspector we see the key/value pairs for the local storage for the current domain.  Additionally, we see the results of reading (again, using the getItem method on the localStorage Javascript object) the data and presenting it, one Email per DIV tag:

Web Storage is supported on all modern browsers.

Conclusion

The localStorage values are shared across every window or tab running at the same origin (same domain) making this an efficient way to not have to repeatedly “make the trip” back to the server for the same data request when you allow your users to navigate from screen to screen.