6

I was thinking that my question is simple but I can't find any answer on the internet at the moment.

In some case I need to create an action but if the user make a change before the response, I want to abort the previous action (if it's still running) and then fire the new action to the server.

I'm using lightning inside a VF page in Salesforce Classic. I'm firing the action using $A.enqueueAction(). The action is set to be ABORTABLE but is never really aborted in my case.

Does anyone got the answer (How to manually abort an action) ?

2

Independent of Lightning, the behavior you've proposed doesn't work in a client-server setup over HTTP . Once the request gets to the network you've no reliable means to make it a noop. Eg the server may already have received the request and started processing it so killing the HTTP connection isn't useful.

It's non-trivial but not impossible to achieve the same objective. It's non-trivial because the operations involved (the network request, server processing) are asynchronous and don't guarantee order across requests. Eg just because request 2 goes out after request 1 doesn't mean that request 2 is received and processed after request 1.

Instead consider: 1. Add a delay after user input and before you enqueue the action. This is often called debouncing the event stream. This'll get you pretty good behavior. 2. To ensure the last action is processed by the server after all previous actions you need to wait for all previous actions to return before enqueuing the last action. This'll ensure correct behavior in all circumstances.

  • I understand and agree with your response about the HTTP connection. I should have add that at the JS level I want to abort the action. In other terms, I want to prevent the callback to be executed if another action has been fired. I have already an idea on how to achieve it but I was thinking that Salesforce would have provide us a tool to do it. – Bartheleway Nov 4 '16 at 10:20
  • There isn't something built into the framework to handle this. But it's a straightforward pure JavaScript solution if you follow my (1) and (2). – Kevin Venkiteswaran Nov 4 '16 at 10:26
  • I think your (1) is interesting especially to limit the number of server call. For the (2), I'm really septic because the user will potentially wait longer plus I don't think that I'm able to control such behavior with Lightning. – Bartheleway Nov 4 '16 at 10:40
2

Here is what I think is the correct answer if Salesforce doesn't provide us a better way to do it.

EDIT : I did include your (1) to the code. Thanks to @Kevin V

EDIT 2 : The code was not Locker Service compliant, now it is.

Helper

({
    uniqueSearchId: null,
    waitingId: null,
    makeSearch: function(component, event, helper) {
        var action = component.get('c.search');
        var searchId = (new Date()).getTime();

        this.uniqueSearchId = searchId;

        action.setParams({
            // Whatever param
        });

        action.setCallback(this, function(a) {
            if (this.uniqueSearchId == searchId && component.isValid()) {
                // Do something with the response
                // like setting the response to a component
            } else {
                // Action aborted because another has been fired
                // Or the component is not valid anymore
            }
        });

        window.clearTimeout(this.waitingId);

        this.waitingId = window.setTimeout($A.getCallback(function() {
            if (component.isValid()) {
                $A.enqueueAction(action);
            }
        }), 250);
    }
})

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.