0

I an trying to return a value from Axios in my JS code. The function always returns null. I want the value to be returned.

function isAbstractSubmitted(proposal_id, version) {

    var isSubmitted = '';


    var that = this;

    axios.post('{{ url("irb/issubmitted") }}', 
        { 
            proposal_id: proposal_id, 
            version: version 
        },
        {
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        })
    .then(function (response) {
        that.isSubmitted = response.data.submitStatus
    })
    .catch(function (error) {
        console.log(error);
    });

    return isSubmitted;

    
}
Patrick Hund
  • 19,163
  • 11
  • 66
  • 95
  • `axios.post` is an asynchronous operation. When it has finished, your synchronous function `isAbstractSubmitted` has already returned `isSubmitted` before it has been set. This is a complex topic which confuses many newcomers (I know it did confuse me back in the day ). Hopefully, this SO post will get you on the right track: https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Patrick Hund Jul 22 '20 at 15:28
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Patrick Hund Jul 22 '20 at 15:29
  • @PatrickHund Well thanks, i am taking a look at that post however how am I to modify the code in order the return the desired results – Zelda Taylor Jul 22 '20 at 15:42
  • You would have to return the promise returned by `axios.post` and any subsequent code that relies on `isSubmitted` being seed would have to be in a `then` of that promise. Another option would be to use the async/await syntax. – Patrick Hund Jul 22 '20 at 15:48
  • @PatrickHund. Can you please the modification with the code I supplied? Thank you. – Zelda Taylor Jul 23 '20 at 06:51
  • I don't know what you changed, but it still won't work. I hope my answer below helps :-) – Patrick Hund Jul 23 '20 at 15:01

1 Answers1

0

The only way to work with results of an asynchronous function call is to make the function that executes the async call also asynchronous, i.e. it has to return a promise.

Think of it this way: axios.post promises to isAbstractSubmitted:

“I'll set isSubmitted for you some day, pinky swear.”

So isAbstractSubmitted would have to return that promise to whatever is calling it – it's not able to return any actual value, because it's only been promised to get a value:

function isAbstractSubmitted(proposal_id, version) {
  return axios.post('{{ url("irb/issubmitted") }}',
    {
      proposal_id: proposal_id,
      version: version
    },
    {
      headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      }
    })
    .then(function (response) {
      return response.data.submitStatus
    })
    .catch(function (error) {
      console.log(error);
    });
}

Any code invoking isAbstractSubmitted will have to deal with the promise, like this, for example:

isAbstractSubmitted('my_proposal_id', 'my_version').then(
  function (submitStatus) {
    if (submitStatus === 'OK') {
      console.log('abstract has been submitted');
    } else {
      console.log('abstract has not been submitted');
    }
  }
)

Once you are in “promise land”, there is no way out of it, all subsequent code relies on the promises made before.

There is, however, a way to change the code so that it at least looks like the familiar synchronous code, namely async/await:

async function isAbstractSubmitted(proposal_id, version) {
  let response = null;
  try {
    response =  axios.post('{{ url("irb/issubmitted") }}',
      {
        proposal_id: proposal_id,
        version: version
      },
      {
        headers: {
          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
      })
  } catch (error) {
    console.log(error);
    return false;
  }
  return response ? response.data.submitStatus : null
}

var submitStatus = await isAbstractSubmitted('my_proposal_id', 'my_version')
if (submitStatus === 'OK') {
  console.log('abstract has been submitted');
} else {
  console.log('abstract has not been submitted');
}

By adding the async keyword to your function, you automatically make it return a promise, but it looks like it's actually returning the promised value.

You can add await to any function call that returns a promise to get the promised value.

Patrick Hund
  • 19,163
  • 11
  • 66
  • 95
  • Thank you very much for taking the time to help me resolve and really start the process of understanding this stuff. I am grateful. – Zelda Taylor Jul 24 '20 at 06:03
  • I'm glad to help. Your problem is actually something people ask about every day, and these questions get close as duplicates all the time. The answer that the duplicate links to is correct, but pretty hard to understand, IMO – Patrick Hund Jul 24 '20 at 06:25