Lesson 6 - Data storage in JavaScript
In today's lesson, we'll look at how we can store data in JavaScript so that we don't lose it again when the page is refreshed.
Web storage
Web storage, or DOM Storage, is the collective name for
localStorage
and sessionStorage
.
localStorage
localStorage
is a repository in the user's internet
browser (therefore local), in which the data in a text
string can be stored, and which we can access later. We have 10MB of
space available for our application, which is really a lot for plain text. The ability to save only text is
quite limiting, but localStorage
is still the most popular data
repository due to its simplicity, and thanks to it we won't lose the data after
the page is refreshed or closed.
Working with localStorage
Working with localStorage
is very simple.
setItem()
setItem()
is a method to store a string under a text index.
Let's try to store the string "John"
under the "name"
key:
localStorage.setItem("name", "John");
We open the script page in a browser, then delete the code and refresh the page again. This way we are sure that John is no longer in the code, but it is stored in the repository.
getItem()
getItem()
is a method to read the value in the key. Now we will
write what is in the key "name"
, which will get us the value
"John"
:
document.print(localStorage.getItem("name"));
Result:
We see that John has really been loaded.
removeItem()
You probably won't be surprised that we can delete a string under a key from
the repository. We do this with the removeItem()
method:
localStorage.removeItem("name");
clear()
We can completely empty the storage from all keys and the data under them
with the clear()
method.
length
The number of items in localStorage
is obtained using the
length
property:
document.write("Stored" + localStorage.length + " items");
Result:
key()
You may have wondered how we can find out what localStorage
is
or how to work with items in the repository in bulk. The last missing method is
therefore key(n)
, where n
is the index - the serial
number of the key we want to return. In combination with the length
property, we can, for example, list all keys in the repository and the values
stored under them. Let's take the last demo, which will really exhaust the
possibilities that localStorage
offers:
for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); document.write(key+ ": " + localStorage.getItem(key) + "<br>"); }
Result:
The code stores 3 values in localStorage
under 3 keys and then
lists the number of items in the store.
The order of the keys may be different in each browser and
therefore our application should not depend on it. Thus, for example, we should
not assume that the first value added will always be below the 0
key.
Storing multiple values under one key
Maybe you are wondering how it is possible to store, for example, an array of values or an object under one storage key? If we didn't group the related values under one key, there would be a real mess in the repository, just try to imagine how we would store 2 users there. Therefore, we convert the whole object to text, which is done in JavaScript using the JSON format. We will learn this in the next lesson and then we will try it out in our PPE diary.
sessionStorage
In addition to localStorage
there is also a
sessionStorage
store. This works exactly the same, but differs in
the context in which the data is stored. The differences are 3:
- The data in
sessionStorage
is unique for each browser tab. Conversely, if we open the same page usinglocalStorage
in multiple tabs, all tabs will use the same repository with the same data. - Data will be lost when the bookmark is closed. Conversely,
the data in the
localStorage
stays in the browser. - So why would we use
sessionStorage
when it is still deleted when you close the page? We could only store data in variables as before, right? ... Well,sessionStorage
, like cookies, remains intact when the page is refreshed or when going to another page in the same domain.
Cookies
You have probably heard about cookies, at least in connection with the European Union and its infamous cookie message.
Cookies have several uses, the most important are 3:
- Storing data in the browser - Cookies have long been the
only way to store something in the browser without losing it when the page is
refreshed. This way we could save, for example, that we have already crossed out
a cookie message on the page
localStorage
repository is currently used for this purpose, see below. There, values are easier to retrieve from the storage and do not strain bandwidth because they are not sent with every request to the server. - User login - Since the browser sends all cookies in the given session together with the request to the server, the user logs in to the server via them. In other words, the value of the user's cookies can be read on the server in languages such as PHP or C # .NET. This use is then described in the relevant server courses.
- Getting information about a user - Google stores in cookies that you searched for a specific product on it. Google ads on other websites will then retrieve from cookies what you are interested in and offer you the goods. Google Analytics works in a similar way, their cookie is on almost every website.
In client JavaScript, there is no longer a very good reason for using cookies, but for completeness we will show how to work with them, you don't have to learn it.
Creating a new cookie
We create a cookie in a slightly strange way by assigning it to the
document.cookie
variable, which contains all the cookies. However,
the assignment to it will not overwrite all cookies, but will add a new one
between them. In order not to end the strangeness of this older API, we create a
cookie as a string of 4 values separated by semicolons, for example as
follows:
"eu_message_canceled=1; expires=Sun, 29 Mar 2020 22:00:00 GMT; path=/"
We enter the cookie:
- Name and value
- Expiration date - If omitted, the cookie is valid until the browser tab is closed. If set to the past, the cookie will be deleted immediately.
- Path - Where the cookie is valid, we usually set the entire
domain to the value
/
.
This hard way of creating a cookie directly tempts to write a function. Its code would be as follows:
function createCookie(name, value, expiration = null) { const expirationTime = expiration ? `expires=${expiration.toGMTString()};` : ''; document.cookie = `${name}=${value}; ${expirationTime} path=/`; } createCookie('eu_message_canceled', 1, new Date(2020, 2, 30));
Retrieve cookie value
Even loading cookies is not very intuitive. We must first load all the cookies in the given document, which is a long text string in which all the cookies of the given page are separated by semicolons. There is only a name and value, the expiration date is handled internally by the browser.
For example, the document.cookie
string looks like this:
_ga=GA1.2.1621812384.1525606041; __gads=ID=fdbec79e49891ee3:T=1525606041:S=ALNI_MYNHHGQJ65wZIjdzOc60pQanykM8w; __qca=P0-718587983-1559900791988; _gid=GA1.2.2042156113.1583272955; _gat=1; eu_message_canceled=1"
It is now up to us to get the value eu_message_canceled
from it.
Of course, we must also take into account that the given cookie maybe does not
exist at all! The function for reading cookies would look like this:
function findCookie(name) { const cookies = document.cookie.split(';') for (const cookie of cookies) { values = cookie.split('='); if (name == values[0].trim()) return values[1].trim(); } return null; } document.write(findCookie('eu_message_canceled'));
Let's try in the browser that it really works:
As already mentioned, all values of all cookies are sent to
the server in the HTTP request header each time each page is loaded. Therefore,
use them only if you cannot use localStorage
.
A cookie set from the server can have the
HttpOnly
property set, which means that we cannot retrieve it from
the client JavaScript. This is a basic security measure that should be set when
using cookies to authenticate users on the server. Of course, this property of
cookies cannot be set from the client JavaScript:)
Delete cookie
Deleting a cookie is the same as creating it, we only set its expiration date, which will lead to its deletion. We can state anything as a value.
IndexedDb
The last standard repository that we can use in JavaScript is IndexedDB. As
the name suggests, it is no longer just a repository, where we store data under
some keys, but a full-fledged database with tables and indexes, which also gave
rise to its name. So we store structured data. Database indexes allow us to
search the database much faster and we are able to work directly with the data
without having to convert it from / to string, as is the case with
localStorage
. In addition, it supports transactions and other
standard database mechanisms that ensure data integrity (that data is not stored
badly, perhaps because an application has encountered an error, simply all or
nothing is stored). Last but not least, it also supports file storage.
The database is so-called NoSQL, which means that we do not communicate with it like in SQL language, as is customary with databases, but by calling methods on database objects. This is sometimes a bit daunting, which is the reason why several superstructures were created for it.
IndexedDB is suitable for larger applications with a more complex data structure and a larger amount of data. Its use exceeds the level of the OOP course and would need a separate course, so we will not deal with it here.
We should not confuse IndexedDB with WebQL, which is another non-standard database that is not supported by all browsers.