Salesforce Lightning: Client side caching using Storable action

Worried about the performance of your lightning components?

Frequent calls to server are degrading the performance of your lightning components?

If yes, then the answer to all such problems is Storable actions. Storable actions in lightning are a way to cache your data at the client side. This is all internally managed by the platform and minimal custom code is required for this. To make an action storable, you simply call its setStorable() function. For example:

var action = component.get("c.getPicklistOptions");
action.setStorable();
action.setCallback(this, function(response) {
    // handle response
};
$A.enqueueAction(action);

How does Storable action works?
If you call the setStorable method before calling the server side method, then the platform compares the previous server call with the current server call. If the parameters to both the server calls are same, then it skips the server call and instead returns the response from the client side cache. This saves the server round trip and improves the overall response of the lightning component.

Lets implement the caching in the picklist component that we created in my last post. We will modify the Picklist component to see how does caching improve the overall performance of the component. Below is the code with caching implemented in it.

Picklist.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="PicklistController">
 
    <!-- required attributes-->
    <aura:attribute name="objectName" type="String" required="true" default="Account"/>
    <aura:attribute name="fieldName" type="String" required="true" default="Type"/>
 
    <!-- optional attributes-->
    <aura:attribute name="label" type="String" default="Label" description="Text that describes the desired select input. Default is the field's label."/>
    <aura:attribute name="value" type="String" description="The value of the select, also used as the default value to select the right option during init. If no value is provided, the first option will be selected."/>
 
    <!-- event handlers, as exposed by lightning:select component -->
    <aura:attribute name="onblur" type="Aura.Action" description="The action triggered when the element releases focus."/>
    <aura:attribute name="onfocus" type="Aura.Action" description="The action triggered when the element receives focus."/>
    <aura:attribute name="onchange" type="Aura.Action" description="The action triggered when a value attribute changes."/>
 
    <aura:attribute name="options" type="List" access="private" description="The picklist options to choose from. Populated during component initialization."/>
 
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
 
    <lightning:select name="picklist"
                      label="{!v.label}"
                      value="{!v.value}"
                      class="{!v.class}"
                      onblur="{!v.onblur}"
                      onfocus="{!v.onfocus}"
                      onchange="{!v.onchange}">
     
        <aura:iteration var="opt" items="{!v.options}">
            <option value="{!opt.value}" selected="{!opt.value==v.value}">{!opt.label}</option>
        </aura:iteration>
    </lightning:select>
 
    <lightning:button variant="brand" label="Fetch picklist values again" title="Fetch picklist values again" onclick="{!c.init}"/>
 
</aura:component>

PicklistController.js
({
init : function(component, event, helper) {
helper.getPicklistOptions(component, event, helper);
}

})

PicklistHelper.js
({
    getPicklistOptions : function(component, event, helper) {
     
        var action = component.get("c.getPicklistOptions");
        action.setStorable();
        action.setParams({ objectName : component.get("v.objectName"),
                          fieldName: component.get("v.fieldName")});
        action.setCallback( this, function( response ) {
            console.log("Page loaded in" , performance.now() - startTime , "ms");
            if (component.isValid() && response.getState() === "SUCCESS") {
                var data = response.getReturnValue();
                component.set("v.options", data);
                component.set("v.value", data[0].value);
            } else {
                console.error("Error calling action: "+ response.getState());
            }
        });
        var startTime = performance.now();
        $A.enqueueAction(action);
    }
})

The change for caching is in PicklistHelper.js where we call action.SetStorable to enable the client side caching. In the callback method, I have put a console log to record the timing. I have added a button called "Fetch picklist values again" in the component which calls the same action to note the time difference. Below is the screenshot of the performance improvement.


The first call to the server takes 280ms whereas the subsequent call in which the result is returned from the cache instead of making a trip to server takes only 3.99ms. That's an improvement of 98.57 % which is great.



Comments

Popular posts from this blog

Salesforce Hacks: System.LimitException: Too many queueable jobs added to the queue: 2

Salesforce Lightning: Countdown timer

Building an Org Role Hierarchy component in LWC