8

I have an apex class associated with lightning component. I have @AuraEnabled methods inside my apex class. Now do I have to use @future(callout=true) method to execute asynchronously ?

Simply my question is, Is it required to call @Future(callout=true) from @auraEnabled Method if I want to make a asynchronous callout?

Adding below question after comments from David

If I want to make an asynchronous callout(As my external system is time consuming and I don't have requirement to show the response in UI), do I have to call Future method from AuraEnabled method ? or by default it will execute asynchronously?

3 Answers 3

15

Is it required to call @Future(callout=true) from @auraEnabled Method if I want to make a asynchronous callout?

If you want to make an asynchronous callout (you do not wait for the result and don't receive a response that you can return to your Lightning component), then yes, you'd need to use an @future method. You might use this, for example, if you need to push data into a remote system but don't need to wait for a response, or if you're firing a long-running remote process and don't want to wait to return a value to the client-side JavaScript controller.

However, it is legal to make a callout from within an @AuraEnabled controller method. If you're calling a web service to return data to your JavaScript controller, you must call the service synchronously, without using @future. This ensures you'll receive a response in the same transaction that you can return to the client-side. For example, this is just fine (in abbreviated example form):

@AuraEnabled
public static serviceResponse getStationTimetable(String station) {

    Http http = new Http();
    HttpRequest req = new HttpRequest();
    req.setEndpoint('SOME_ENDPOINT' + EncodingUtil.urlEncode(station, 'UTF-8'));
    req.setMethod('GET');

    HttpResponse res = http.send(req);

    return JSON.deserialize(res.getBody(), serviceResponse.class);
}

What does Asynchronous Mean Anyway?

Let's be clear about our terms here, because we have several layers of functionality that can be described as either synchronous or asynchronous.

From the client side, in your JavaScript controller, you invoke server actions asynchronously. This means that you enqueue the action and let the framework take over from there, understanding that you'll get a callback when the action completes successfully or unsuccessfully. You don't block waiting for the response.

On the server side, an @AuraEnabled method executes synchronously - i.e., at the moment it's called by the Lightning framework, and in a single transaction. It's not enqueued on the server in the way that an @future or Queueable would be.

Callouts are really always executed synchronously when you look at the send() method itself. When you fire a callout, your transaction waits for the results. The distinction is that you cannot fire callouts from certain types of Apex (specifically, triggers), and for this reason we push them into an asynchronous Apex context, such as an @future method or a Queueable.

They still execute synchronously in that context, but from the perspective of the Apex code that started the operation (such as the trigger, or an @AuraEnabled method), the callout takes place asynchronously and in a separate transaction. That's what we mean when we talk about an asynchronous callout in Apex.

9
  • You mean by default @AuraEnabled method will run Synchronously ?
    – Manu Tej
    Commented Nov 20, 2018 at 14:20
  • 2
    In the sense that it runs in a single Apex transaction, yes. From the JavaScript controller's perspective, the server action is asynchronous.
    – David Reed
    Commented Nov 20, 2018 at 14:24
  • It doesn't make sense to call future method from @auraEnabled method as it is already asynchronous. Commented Nov 20, 2018 at 14:42
  • @Gourav I agree that it would be unusual, but I can imagine a situation where it was desired, particularly with a non-performant or badly-behaved web service.
    – David Reed
    Commented Nov 20, 2018 at 14:44
  • If I want to make an asynchronous callout(As my external system is time consuming and I don't have requirement to show the response in UI), do I have to call Future method from AuraEnabled method ? or by default it will execute asynchronously?
    – Manu Tej
    Commented Nov 20, 2018 at 14:47
8

The Apex code called from the Lightning Controller is synchronous. I think your misunderstanding comes from the idea that you need to perform a callout asynchronously. This is not true. The only time you need to perform a callout asynchronously is if you've already started or completed at least one DML operation in the current transaction. This means that callouts performed from triggers must always be asynchronous. The rest of the time, such as in Visualforce or Lightning controllers, you do not need to perform a callout asynchronously as long as you do not violate the DML-before-callout rule.

2
  • +1 from me. I guess only thing that confuses me is the first line. Call from controller to apex being synchronous! Commented Nov 20, 2018 at 14:44
  • 2
    @codeyinthecloud No, you're right, it was a bit confusing. I've clarified. The problem is that you have two systems (client, server); from the client side, the call is asynchronous, but from the server side, it is synchronous code (and has synchronous code limits as defined by governor limits).
    – sfdcfox
    Commented Nov 20, 2018 at 14:50
1

$A.enqueueAction(action which calls the @auraEnabled method) adds the server-side controller action to the queue of actions to be executed. All actions that are enqueued will run at the end of the event loop. Rather than sending a separate request for each individual action, the framework processes the event chain and batches the actions in the queue into one request.

The actions are asynchronous and have callbacks. These actions are asynchronous for server round trips. And also because of the queuing you won't see concurrent execution here.

Future Methods :

A future method runs in the background, asynchronously. You can call a future method for executing long-running operations, such as callouts to external Web services or any operation you’d like to run in its own thread, on its own time.

You can also make use of future methods to isolate DML operations on different sObject types to prevent the mixed DML error. Each future method is queued and executes when system resources become available. That way, the execution of your code doesn’t have to wait for the completion of a long-running operation. A benefit of using future methods is that some governor limits are higher, such as SOQL query limits and heap size limits.

To your question. Yes you do have to call a future method to make an Asynchronous callout from server side if not you will have to do a client side AJAX callout. But like @DavidReed and @sfdcfox suggested you don't necessarily need an asynchronous callout in context of a lightning component!

2
  • 1
    ... but it's quite all right to make a synchronous callout from the body of an @AuraEnabled method. I think the synchronous/asynchronous thing is extra confusing here.
    – David Reed
    Commented Nov 20, 2018 at 14:37
  • 2
    @DavidReed I agree. The term actions are asyncronous is confusing as they are only in the context of server trips as they run their own transaction thread. But when it comes to server as far as its concerned its just a single thread which is synchronous in its own nature. Commented Nov 20, 2018 at 14:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .