Skip to content

Modus-Logo-Long-BlackCreated with Sketch.

  • Services
  • Work
  • Blog
  • Resources

    OUR RESOURCES

    Innovation Podcast

    Explore transformative innovation with industry leaders.

    Guides & Playbooks

    Implement leading digital innovation with our strategic guides.

    Practical guide to building an effective AI strategy
  • Who we are

    Our story

    Learn about our values, vision, and commitment to client success.

    Open Source

    Discover how we contribute to and benefit from the global open source ecosystem.

    Careers

    Join our dynamic team and shape the future of digital transformation.

    How we built our unique culture
  • Let's talk
  • EN
  • FR

localStorage Caching of Reference Data with ExtJS

Published on October 15, 2012
Last Updated on February 26, 2021
Application Development

Do you have a ton of reference data that needs to load with your app? Lots of combo boxes with mostly static data? Previously I had used a custom store extension to handle caching of the data in memory. That approach involved flipping between use of a MemoryProxy and a RestProxy depending upon whether the data was cached or not. As I found later on, this breaks down when you need to administer that reference data. Why? Because with a MemoryProxy, there’s no way to make remote calls for create, update and destroy operations of course! #facePalm

So with my new administration requirements I needed a new approach. And that meant using a custom proxy, rather than a custom store. What I needed was the ability to write a simple store configuration as below, have it pull from the cache whenever possible on read operations and perform normal REST behavior on all write operations.

Ext.define('MyApp.store.reference.Country', {
    extend: 'Ext.data.Store',
    model: 'MyApp.model.reference.Country',
    proxy: {
        type: 'cachedrest',
        cacheName: 'Country',
        url: 'api/country',
        useLocalStorage: true
    }
});

Note: I’m not attempting to reconcile stale data at this time. I will be incorporating a system for clearing and updating the cache at a later time. But you will see that clearing the cache should not introduce any significant complexity into the proxy or store configurations.

In the above, I can then choose to use localStorage or memory for caching and this store will behave normally (i.e. fire all the correct events and maintain the normal store/proxy API). So I can use autoLoad: true and store.load(), listen for beforeload and load events and so forth. Let’s now take a look at what this proxy will look like. I’ve only included the “in memory” functionality to just demonstrate the basics of how this works.

Ext.define('MyApp.data.CachedRestProxy', {
    extend: 'Ext.data.proxy.Rest',
    alias : 'proxy.cachedrest',

    useLocalStorage: true,

    read: function(operation, callback, scope) {
        var cachedResponse = this.getCachedResponse();

        if (!cachedResponse) {
            this.callParent(arguments);
        } else {
            this.processResponse(true, operation, null, cachedResponse, callback, scope, true);
        }
    },

    getCachedResponse: function() {
        var response = MyApp.data[this.cacheName];
        if (response) {
            return Ext.decode(response);
        }
    },

    setCachedResponse: function(response) {
        MyApp.data[this.cacheName] = response;
    },

    processResponse: function(success, operation, request, response, callback, scope, isCached) {
        // Only cache successful responses that didn't come from the cache
        if (success === true && !isCached) {
            this.setCachedResponse(response.responseText);
        }

        this.callParent(arguments);
    }
}, function() {
    Ext.ns('MyApp.data');
});

Basically, we’re just overriding the read behavior to do the following: if there’s data in the cache, process it; otherwise let the RestProxy do its standard work. Whenever a successful, remote read operation is performed, overwrite the data in the cache.

Now we’ll look at incorporating localStorage. First, we’ll add a config option called useLocalStorage, allowing us to use localStorage for some stores but not for others. Then we’ll use that configuration in our getCachedResponse() and setCachedResponse(). Of course we’ll also have to consider browsers that do not support localStorage and automatically have those behave as if useLocalStorage is false.

    getCachedResponse: function() {
        var response;

        if (this.useLocalStorage && window.localStorage) {
            response = localStorage[this.cacheName];
        } else {
            response = MyApp.data[this.cacheName];
        }

        if (response) {
            return Ext.decode(response);
        }
    },

    setCachedResponse: function(response) {
        if (this.useLocalStorage && window.localStorage) {
            localStorage[this.cacheName] = response;
        } else {
            MyApp.data[this.cacheName] = response;
        }
    }

Lastly, we’re going to want a way to force reading of fresh data. We’ll want to be able to say store.load({forceRequest:true});. To accomplish this, we’ll make a small change to read() as follows:

    read: function(operation, callback, scope) {
        var cachedResponse = this.getCachedResponse();

        // Perform normal RestProxy behavior if fresh data is requested or no cached data exists.
        // Otherwise simply process the cached data.
        if (operation.forceRequest || !cachedResponse) {
            this.callParent(arguments);
        } else {
            this.processResponse(true, operation, null, cachedResponse, callback, scope, true);
        }
    }

And that’s it! Hope this is helpful for you all and please stay tuned as I’ll surely be adding another post around expiring data in localStorage and clearing my reference data cache.

Posted in Application Development
Share this

Jay Garcia

Jay Garcia is co-founder of Modus Create. He is a veteran of the U.S. Air Force with 20-plus years of technology and consulting experience in leading RIA development for companies around the world. He is a co-organizer of the NoVa.JS and NYC.JS meetups, and is actively involved in the software communities that provide business frameworks and technologies, which enable rich mobile and desktop web experiences.
Follow

Related Posts

  • Why You Should Never Ignore Qualitative Data
    Why You Should Never Ignore Qualitative Data

    I recently started listening to Jared Spool’s UIE Podcast during my morning commute into the…

  • How to Use Test Data for Increased Software Quality
    How to Use Test Data for Increased Software Quality

    Test data is a major influencer of test reliability and should be the main concern…

Want more insights to fuel your innovation efforts?

Sign up to receive our monthly newsletter and exclusive content about digital transformation and product development.

What we do

Our services
AI and data
Product development
Design and UX
IT modernization
Platform and MLOps
Developer experience
Security

Our partners
Atlassian
AWS
GitHub
Other partners

Who we are

Our story
Careers
Open source

Our work

Our case studies

Our resources

Blog
Innovation podcast
Guides & playbooks

Connect with us

Get monthly insights on AI adoption

© 2025 Modus Create, LLC

Privacy PolicySitemap
Scroll To Top
  • Services
  • Work
  • Blog
  • Resources
    • Innovation Podcast
    • Guides & Playbooks
  • Who we are
    • Our story
    • Careers
  • Let’s talk
  • EN
  • FR