0

I have quite an issue for some time and is getting on my nerves and it doesn't make sense. I have used axios on my react frontend and it works perfect when assigning the get value to the state. But when using it in a normal javascript code, I appear to have this following issue: i can print the object's value in the console but it will return only undefined.. Here is my code:

login = () => {
        let data;
        axios.get('https://myaddress/authenticate')
            .then(response => {
                data = response;
                console.log('data here', data);
            })
            .catch(error => {
                console.error('auth.error', error);
            });
        console.log('eee', data);
        return data;
    };

Here we are talking about axios strictly.

some guy
  • 45
  • 1
  • 2
  • 8
  • 3
    Possible duplicate of [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) – Robin Zigmond Nov 21 '18 at 13:40
  • @RobinZigmond it is not, here we are talking about axios strictly – some guy Nov 21 '18 at 13:44
  • 2
    the specifics of the library don't matter, it's still asychronous, so the same issues and same possible solutions are all relevant. – Robin Zigmond Nov 21 '18 at 13:47

2 Answers2

5

You can't return an ajax response because it's asynchronous. You should wrap your function into a promise or pass a callback to login

UPDATE: As @Thilo said in the comments, async/await would be another option, but it will let you set the response to data tho ...

1. Wrap into a promise

 login = () => new Promise((resolve, reject)=>{
      axios.get('https://myaddress/authenticate')
      .then(response => {
           resolve(response)
      })
      .catch(error => {
           reject(error)
      });
 });

 // Usage example
 login()
    .then(response =>{
       console.log(response) 
    })
    .catch(error => {
       console.log(error)
    })

2. Pass a callback

login = (callback) => {

   axios.get('https://myaddress/authenticate')
        .then(response => {
            callback(null,response)
        })
        .catch(error => {
            callback(error,null)
        });
};

// Usage example
login((err, response)=>{

     if( err ){
       throw err;
     }

     console.log(response);

})

3. Async/Await

login = async () => {

  // You can use 'await' only in a function marked with 'async'

  // You can set the response as value to 'data' by waiting for the promise to get resolved
  let data = await axios.get('https://myaddress/authenticate');

  // now you can use a "synchronous" data, only in the 'login' function ...
  console.log('eee', data);

  return data; // don't let this trick you, it's not the data value, it's a promise

};

// Outside usage
console.log( login() ); // this is pending promise
darklightcode
  • 2,738
  • 1
  • 14
  • 17
  • Why wrap the promise that Axios returns into another one instead of using it directly? – Thilo Nov 21 '18 at 13:58
  • But how I save the promise's value and store in a variable so I can use it ?? – some guy Nov 21 '18 at 13:59
  • 1
    @Thilo i know it's a weak example and i was very close not writing it, but yet i did, in case he wants to split some logic into `axios` then and resolve it afterwards so `login().then()` would be cleaner – darklightcode Nov 21 '18 at 14:01
  • 2
    I'm just worried that it makes it look like more boilerplate than there really has to be (making the callback solution look more attractive than it should be). Maybe bring up `async/await` as well. OTOH, it's a dupe anyway. – Thilo Nov 21 '18 at 14:02
  • @Thilo nice catch, i really forgot about `async/await`, i don't use it on a daily basis, i love my callback hell – darklightcode Nov 21 '18 at 14:33
  • Why would you return a pending promise from async function? – squeekyDave Nov 21 '18 at 14:44
  • @squeekyDave i kept the `return data` from OP method, and i commented about what really happens with it. I've seen people expecting their async method to be 'sync' when using it outside under some kind of comment that "my variable was sync there so the method will return sync". It's mostly a misunderstanding about async/await. Examples(even the bad ones) and a few comments will always shed some light in the callback hell. – darklightcode Nov 21 '18 at 14:55
  • @darklightcode The whole point of **async/await** is to transform async code into sync and improve upon readability and data flow. By returning a promise, it means you havent really taken full advantage of what async/await can do, seems a bit pointless to me because first, the promise has to be resolved aftwerwords, second, if the promise is rejected, trailing back from where the rejection occured doubles the work. – squeekyDave Nov 21 '18 at 15:00
  • @darklightcode using third method, I still get a Promise back – some guy Nov 22 '18 at 08:55
0

In ES7/ES8 you can do async/await like a boss:

login = () => {
  return new Promise((resolve, reject) => {
      axios.get('https://myaddress/authenticate')
        .then(response => {
            resolve(response)
          })
          .catch(error => {
              console.error('auth.error', error);
              reject(error)
          });
  });     
};

  async function getData() {
    try{
      const data = await login()
    } catch(error){
      // handle error
    }
    return data;
  }
  getData()
  .then((data) => console.log(data));
squeekyDave
  • 918
  • 2
  • 16
  • 35