4

From the salesforce promise documentation:

Don’t Use Storable Actions in Promises

The framework stores the response for storable actions in client-side cache. This stored response can dramatically improve the performance of your app and allow offline usage for devices that temporarily don’t have a network connection. Storable actions are only suitable for read-only actions.

Storable actions might have their callbacks invoked more than once: first with cached data, then with updated data from the server. The multiple invocations don't align well with promises, which are expected to resolve or reject only once.

Should that deter me from using promises with the following use cases:

  1. I have to retrieve the current user information across multiple components before I allow a callback to the server.

  2. I also have to grab the entire role hierarchy to determine the roles above the user in order to determine the public group relationships from the group member table.

Both sets of this info would remain relatively static and would likely benefit from storable actions. If I do this across 4-5 components on the same app page, I think that would degrade performance, especially in the latter use case. How much of a hit would be taken from using a storable actions with promises, if any?

  • I received 148-152 ms for using a storable action with the component. I received 600-100 ms varying on the component without using a storable action with the component. This leads me to believe that storable actions, even though the documentation says that it may not lend itself to promises, still drastically increases performance time when used. – jmdohn Jun 30 '17 at 18:28
  • with ur use case, you should be safe to use storable actions and promises. wat the doc says is if its a more frequently changing data, then chaining callbacks with promises is risky because your follow up actions will be performed multiple times everytime the framework retrieves & refreshes the cached data. – Vamsi Krishna Jun 30 '17 at 18:43
1

I've been thinking about this too as I'd like to build a reusable utility that can make metadata describe info available in Lightning. This falls under the "rarely changing info" category so it might be a place where it's OK to mix storables and promises.

I've also been thinking though about what kind of patterns might be possible if you wanted to account for the second return. First off there is a way to know whether the callback is running a second time:

var action = cmp.get("c.myAction");
var firstTime = true;
action.setCallback(this, function(response) {
    if (firstTime){
        firstTime = false;
        // Do whatever logic is appropriate for first callback execution
    }
    else {
        // Do whatever logic is appropriate for second callback execution
    }
};
$A.enqueueAction(action);

But now what do you do when you want to connect that to a Promise? What we need is a way to signal "Do this when a response comes back, but also do this other thing when a second response comes back, if it does."

So I have no idea if someone can come up with a better architecture but here is my thought:

executeAction: function (cmp, action) {
    var p1,p2,resolve2,reject2;
    var firstTime = true;

    p2 = new Promise(function(resolve, reject){
        resolve2 = resolve;
        reject2 = reject;
    });

    p1 = new Promise(function(resolve1, reject1) {
        action.setCallback(this, function (response){
            // which resolve function to use?
            var resolve = firstTime ? resolve1 : resolve2;
            var reject = firstTime ? reject1 : reject2;
            firstTime = false;

            if (response.getState() === 'SUCCESS') {
                resolve(response.getReturnValue());
            } else if(response.getState() === 'ERROR'){
                reject(response.getError());
            }
        });
        $A.enqueueAction(action);
    });

    return [p1,p2];
}

You'd pass an action into this function and get an array with two promises, [p1,p2]. The first (and possibly only) time a value returns, it will resolve p1. If a second time happens, it will resolve p2. So this way you can specify different behaviours to follow through with if p1 is returned vs p2.

A somewhat messy thing is that we export the resolve and reject functions of p2 so that they can be addressed in the scope of p1's function. But this gives us the ability to choose which promise resolves when the callback executes.

Any better ideas? Comments/suggestions?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.