2

I want to have the value of Helper class's function who calls Apex method and return the state to controller from where it is being called?

For eg. below is the code :

DummyController.js
    callHelper : function(component,event,helper){
        var isSuccess = helper.createRecord (component,'dum1');
        console.log(isSuccess);
    }

DummyHelper.js
    createRecord : function (component,recordName){
       var action = component.get('c.apexCreateRecord'); // calls an apex method
       action.setParams({
           'name' : recordName
       });
       action.setCallback(this, function(response) {
         var state = response.getState();
         return state; // Want this state value to above controller's variable isSuccess. 
       });
       $A.enqueueAction(action);
    }

Is this possible or is there any other way to achieve this? Currently when I debug this in console it calls console.log line before helper's function response. Thanks.

2 Answers 2

6

In Aura, you can use a Promise to wait for the result. That would look like this:

callHelper: function(component,event,helper){
    helper.createRecord(component,'dum1')
    .then(function(result) {
       console.log(result);
    });
}

  createRecord: function(component, recordName) {
    return new Promise(
      $A.getCallback(function(resolve, reject) {
        var action = component.get("c.apexCreateRecord"); // calls an apex method
        action.setParams({
          name: recordName
        });
        action.setCallback(this, function(response) {
          var state = response.getState();
          resolve(state);
        });
        $A.enqueueAction(action);
      })
    );
  }

Notice how it looks almost identical, except that you wrap everything up in a return new Promise($A.getCallback(function(resolve, reject) {...})) design. You can actually codify this in to a helper method that you can use everywhere. That looks like this:

server: function(component, actionName, params) {
    return new Promise($A.getCallback((resolve, reject) => {
        var action = component.get(actionName);
        params && action.setParams(params);
        action.setCallback(this, result => {
            switch (result.getState()) {
                case "DRAFT":
                case "SUCCESS":
                    resolve(result.getReturnValue());
                    break;
                default:
                    reject(result.getError());
            }
        });
        $A.enqueueAction(action);
    }));
},

This is in the helper. Once you have that, you can do something like this:

callHelper: function(component, event, helper) {
  helper.server(component, 'c.apexCreateRecord', { name: 'dum1' })
    .then(result => { /* deal with result */ })
    .catch(error => { /* there was an error, deal with it */ });
}
2
  • Thanks that worked. Just one more question now in the helper function I was calling another helper function like this.showToast(component,msg); now as I changed the logic as above added promise it now throws error saying method doesn't exist. Any idea on this one?
    – Jenil
    Mar 25, 2020 at 3:52
  • @Juhi You can use the helper reference still: helper.showToast(component, msg).
    – sfdcfox
    Mar 25, 2020 at 3:53
3

Your Apex action is called asynchronously from helper.createRecord(). It does not execute until after createRecord() itself returns, so it's not possible to synchronously return its result value to the calling method, callHelper() - and you certainly wouldn't want the code that's running in your UI to block waiting for an asynchronous function to return, as that'd yield a poor and unresponsive user experience.

Instead, use your component's attributes as the storage location for this data, and execute any required logic in your action's callback function, which runs upon the conclusion of the Apex method. Populate the isSuccess value into an attribute, on which you can, if necessary, execute a change handler, or simply update other attributes in your callback function based on the result of the Apex method.

1
  • You can't actually wait for a server-side call if you wanted to. The API simply has no mechanism that allows it. Promises are a super-handy way to write code that looks synchronous but actually isn't.
    – sfdcfox
    Mar 25, 2020 at 3:15

You must log in to answer this question.

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