1

Here is the situation. I have a @Future method which has callouts is running along side of actual main CLASS. in the callout response, I am receiving some error/success XML, I am saving them in a STRING message. However, I can not show error from the String RETURN as @future will not send anything like that. So, I am saving that String in another custom Field and updating at the end of FUTURE method. Now, I want to show that field message in Lightning. Can anyone tell me how can I get it done?
Once we are proceeding, Main class executing and exiting then future method getting executed within a few millisec. I want to wait for 5 seconds after we run it in lightning so that I can use the updated field in @future method to show error.

It's a bit complicated it seems but I am not getting any clue. Please help. Thank you, Ashok Kumar.

  • Do you want prevent users from using the page while the future method does a callout and stores the response in that field? – ajinkyah Aug 30 '18 at 12:25
  • @ajinkyah Yes, I want to show something like PLEASE WAIT for 2-3 sec and show the message on that field. – AshSFcloud Aug 30 '18 at 12:36
  • And any reason you need it to be future method? Can't you do the callout in the AuraEnabled method in your controller class for the component? We mostly do future if the callout is being made from trigger or we know that it may require time and should not block other user actions. – ajinkyah Aug 30 '18 at 12:41
  • 1
    You are trying to mix asynchronous operation in a synchronous way. That's not how it should be implemented. If you are using @future that means you want the code to be executed asynchronously, and in that case you should not even wait to capture any results real-time because you cannot really guarantee when your future calls complete. You should definitely revisit your requirements here before going for any implementation. – Jayant Das Aug 30 '18 at 14:58
  • @ajinkyah The reason why I am using Future method is because I am performing an INSERT operation on the same thread. We can not make DML and callouts in the same thread. Also, I am updating those objects with a new values from the response. Based on the response, I can show if it is success or a failure to the user. – AshSFcloud Aug 31 '18 at 4:03
0

To answer your actual question, here is how you can call a method after a wait period:

ControllerJS

callbackOnceAfterDelay : function(component, event, helper) {
        var delayInMilliseconds = 5000; //5 seconds
        window.setTimeout(
            $A.getCallback(function() {
                console.log('myHelperMethod EXECUTING NOW... ');
                helper.myHelperMethod(component, event, helper);
            }), delayInMilliseconds
        );     
    }

But, I don't think it is an elegant approach, just because you are assuming that the future method will complete in 5 seconds. Why keep the user waiting if it returns in 1 second? And what if it takes more than 5 seconds... you won't show a message at all!

Because you mentioned that a field will be updated with the error message after the callout returns, why not regularly check for an update to that field like so:

ControllerJS

callbackAfterEveryNSeconds : function(component, event, helper) {
        var intervalInMilliseconds = 1500; //1.5 seconds interval between each call
        var processId = window.setInterval(
            $A.getCallback(function() {
                console.log('myHelperMethod EXECUTING NOW... ');
                helper.setErrorMessageIfUpdated(component, event, helper); 
            }), intervalInMilliseconds
        );
        component.set("v.processId", processId); 
    },

HelperJS

setErrorMessageIfUpdated: function(component, event, helper) {
        //do a server side action here, check if error field has been updated
        //if so, do component.set("v.errorMessage", response.getReturnValue()); 
        //show the error message if not blank
        //clear the interval for repeating anymore like so: window.clearInterval(component.get("v.processId"));
    },

Notice that window.setTimeout executes once after a set delay. On the other hand, window.setInterval executes over and over after a set time period (so make sure it stops after your callout returns).

And also, did you know that you can detect changes to a specific value and fire a method when that happens? Like so: (just food for thought... you might end up not needing it at all)

<aura:handler name="change" value="{!v.record.My_Callout_Error_Message_Field__c}" action="{!c.showErrorMessageIfAny}"/>
  • I am curious, how your last solution will work? How <aura:handler will get to know about the backend changes? – Saroj Bera Aug 30 '18 at 14:07
  • It might not be super useful for this specific question (that's why I added 'just food for thought... you might end up not needing it at all'), but if you are asking how the change handler works in general, this should help: developer.salesforce.com/docs/atlas.en-us.lightning.meta/… But if your question is how it applies in the context of this specific question, then yeah, {!v.record} needs to be somehow updated for the change handler to fire. – Lightning Evangelist Aug 30 '18 at 14:10
  • No, the change handler won't work. Nothing will tell the v.record to refresh itself when the @future resolves. The only way I've seen this work is to attach an instance of Lightning Data Service and listen to the recordUpdated attribute. You can listen to process builder updates this way, but I'm not sure about @future resolves. – tsalb Aug 30 '18 at 17:20

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.