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.