LearnUsing localForage for Offline Data Storage

“Boxing day!” by Erich Ferdinand/Flickr
   
Avatar

Matt West
writes on March 15, 2014

(Photo by Erich Ferdinand/Flickr)

An important step on the path toward robust, offline web applications is the ability to store data in the user’s browser. Technologies like IndexedDB and localStorage have provided this functionality to web developers, but they are not without their limitations.

The localStorage API is really simple to use, but you can only store text data. This limitation can generally be overcome by storing other types of data as JSON strings, but this can be a pain as you have to encode/decode JSON every time you need to store or retrieve some data. Not to mention you still have a problem if you need to store Blobs or files. LocalStorage is also a synchronous API, which means that your app could hang while data is being stored or retrieved.

IndexedDB, on the other hand, is an asynchronous API that includes great support for a wide range of data types, but the API itself is considerably more complex to use.

Enter localForage, a JavaScript library that provides the ease of use of localStorage with all the advanced features of IndexedDB.

An Introduction to localForage

The localForage JavaScript library was developed by the good folks at Mozilla to provide a simple storage API that has all the capabilities of more complex APIs like IndexedDB, but without the steep learning curve.

Behind the scenes, localForage uses native browser technologies like IndexedDB, WebSQL, and localStorage to actually store data. The localForage API sits on top of this datastore layer and provides a number of methods that can be used for managing data.


Note: WebSQL was dropped in favor of IndexedDB, but some browsers still include support for the WebSQL API.


The other main benefit of using localForage is that you don’t have to convert your data structures to JSON in order to save them in the datastore. If the underlying datastore technology (read: localStorage) doesn’t support the data type you provide, then localForage will take care of the JSON wizardry for you so you can just focus on building your app’s functionality.

Downloading the localForage Library

You can download a copy of localForage from the project’s home page.

Download localForage

Once you’ve downloaded the code archive, copy the localforage.js file found in the dist folder into your project. You can include this file in your web pages using a simple <script> element.

<script src="/path/to/localforage.js"></script>

Licensing: localForage is released as free software under an Apache 2.0 license.


Storing Data

The localForage library will automatically set up a datastore using the best storage technology that’s available in the user’s browser.

As with localStorage, the data is stored using key/value pairs. The setItem method is responsible for saving data in the datastore.

localforage.setItem('key', 'value', callbackFunction);

The value here can be any kind of data you want: a string, number, object, or even a file.

If the key already exists in the datastore, the existing value will simple be overwritten.

Unlike with localStorage, the localForage API is asynchronous and therefore you shouldn’t expect the setItem method to return a value. Instead, you can pass a callback function to the setItem method. This callback function will be executed once the data has been stored and will be passed the value that was saved in the datastore.


Note: The amount of storage space accessible to localForage is governed by the underlying datastore technology that’s being used. For localStorage, the general limit is 5MB, although this may vary among browsers. More space is available when IndexedDB is being used, but the user may be prompted to approve additional quota if your app needs to store large amounts of data.


Retrieving Data

Data can be retrieved from the datastore using the getItem method. You should pass in the key of the item you wish to retrieve, as well as a callback function that will be passed the value for the item.

localforage.getItem('key', callbackFunction);

If the specified key doesn’t exist in the datastore, the callback function will be passed null.

Deleting Data

If you want to delete some data, you can use the removeItem method. Pass in the key of the item you wish to delete and a callback function.

localforage.removeItem('key', callbackFunction);

Clearing The Datastore

You can remove all the data from the datastore using the clear method.

localforage.clear(callbackFunction);

Again, this method can be passed a callback function that will be executed when the operation has completed.

Requesting The Number of Keys in The Datastore

The length method can be used to retrieve the number of items that are currently in the datastore.

localforage.length(callback);

Finding a Key in The Datastore

The localForage API also includes a method that can be used to retrieve a key based on its position within the datastore.

localforage.key(n, callback);

This method is particularly useful if you need to loop over each of the items in the datastore. For example:

// Find the number of items in the datastore.
localforage.length(function(length) {
    // Loop over each of the items.
    for (var i = 0; i < length; i++) {
        // Get the key.
        localforage.key(i, function(key) {
            // Retrieve the data.
               localforage.getItem(key, handleData);
        });
    }
});

localForage Supports Promises!

So far in this post I’ve shown that each of the methods in the localForage API can be passed a callback function. I’ve used these in the traditional manner of adding the callback function as a parameter in the method call. However, there is an alternative.

The localForage API includes support for ECMAScript 6 Promises, which provide a better way of handling asynchronous code. (If you’re not comfortable with using Promises, feel free to pretend this section doesn’t exist.)

Here’s an example of how you can use Promises rather than callbacks when retrieving an item from the datastore.

localforage.getItem('key').then(function(value) {
    console.log(value);
});

Browser Support

The localForage library will work in all modern web browsers. Some older browser versions may not support IndexedDB or WebSQL, in which case the library will use localStorage instead. This means that calls to the API will be executed synchronously in these browsers.

IE Firefox Chrome Safari Opera
10 10 23 3.1 15

The localForage library also has great support for mobile browsers.

Android Browser Blackberry Chrome for Android Firefox for Android Firefox OS IE Mobile Safari Opera Mobile
2.1 7 32 25 1 10 3.1 11

Source: https://github.com/mozilla/localForage#supported-browsersplatforms

Summary

By providing an easy-to-use API that abstracts away the complexity of other storage technologies like IndexedDB, localForage has become a compelling storage solution for building offline web applications. It’s certainly something that I’ll be looking to use in future projects.

What do you think about localForage? Share your thoughts in the comments below.

Useful Links

GET STARTED NOW

Learning with Treehouse for only 30 minutes a day can teach you the skills needed to land the job that you've been dreaming about.

Get Started

10 Responses to “Using localForage for Offline Data Storage”

  1. Hi,
    Local forage performance is far more worse then local srtorage. We we angularjs application we are caching our api call responce in local storage. To improve the performance I tried local forage with indexedDB but read time is too slow with indexed db. Is there a way to achieve fast reading and writing with local storage?

  2. LocalForage doesn’t work well with any IE under 11.
    The lack of support for promises, (even in the no-promises version of localForage) causes headaches trying to get it working on anything under IE11. I swapped to store.js instead, much smoother sailing.

  3. A very good read. Understood the concept with clarity. Thanks a lot!

  4. Prabhu Chincholikar on February 2, 2016 at 8:11 am said:

    Can localForage Supports FileAPI for reading and writing?

  5. Prabhu Chincholikar on February 1, 2016 at 4:45 pm said:

    Good article.
    I have one question here. If a browser is not compatible with WebSQL and IndexedDB, What is the maximum storage it can support? is it 5 MB for Local Storage?

  6. How do you mock localForage in your tests? Let’s say there’s a need to mock localForage.getItem and return ‘value’. I initially tried to mock the promise but it didn’t work:

    beforeEach(function(){
    spyOn($localForage, ‘getItem’).and.returnValue($q.when(‘value’));
    }

  7. Before this I use ngStorage – https://github.com/gsklee/ngStorage. I found that this localForage is good too. Looking forward to use it in my next project. Thanks!

  8. Interesting read, thanks for sharing, I might give it a try this weekend 🙂

  9. Do any of these provide any additional security? My understanding is that, right now, any Javascript has automatic access to all the localStorage associated with that page, whether it be set from the same script or not. Seems like it should be used with caution.

    • Not that I’m aware of. The datastores are sandboxed to the domain so any JavaScript that runs on the site can access the data.

      I see the security concern here but you probably shouldn’t be using client-side storage for sensitive data anyway. If you’re building a purely offline web app the risk of having a malicious script access the data is somewhat reduced.

      You could look into JavaScript encryption methods for protecting data (https://code.google.com/p/crypto-js/) but this is probably overkill.

Leave a Reply

You must be logged in to post a comment.

man working on his laptop

Are you ready to start learning?

Learning with Treehouse for only 30 minutes a day can teach you the skills needed to land the job that you've been dreaming about.

Start a Free Trial
woman working on her laptop