13

I am having trouble wrapping my head around returning json data from a fetch() call in one function, and storing that result in a variable inside of another function. Here is where I am making the fetch() call to my API:

function checkUserHosting(hostEmail, callback) {
    fetch('http://localhost:3001/activities/' + hostEmail)
    .then((response) => { 
        response.json().then((data) => {
            console.log(data);
            return data;
        }).catch((err) => {
            console.log(err);
        })
    });
}

And this is how I am trying to get the returned result:

function getActivity() {
    jsonData = activitiesActions.checkUserHosting(theEmail)
}

However, jsonData is always undefined here (which I am assuming is because the async fetch call has not finished yet when attempting to assign the returned value to jsonData. How do I wait long enough for the data to be returned from the fetch call so that I can properly store it inside of jsonData?

Surfero
  • 167
  • 1
  • 1
  • 8
  • 1
    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) – 4castle Dec 02 '17 at 02:45

3 Answers3

33

always return the promises too if you want it to work: - checkUserHosting should return a promise - in your case it return a promise which return the result data.

function checkUserHosting(hostEmail, callback) {
    return fetch('http://localhost:3001/activities/' + hostEmail)
        .then((response) => { 
            return response.json().then((data) => {
                console.log(data);
                return data;
            }).catch((err) => {
                console.log(err);
            }) 
        });
}

and capture it inside .then() in your main code:

function getActivity() {
    let jsonData;
    activitiesActions.checkUserHosting(theEmail).then((data) => {
       jsonData = data;
    }        
}

EDIT:

Or even better, use the new syntax as @Senthil Balaji suggested:

const checkUserHosting = async (hostEmail, callback) => {
 let hostEmailData  = await fetch(`http://localhost:3001/activities/${hostEmail}`)
 //use string literals
 let hostEmailJson = await hostEmailData.json();
 return hostEmailJson;
}

const getActivity = async () => {
 let jsonData = await activitiesActions.checkUserHosting(theEmail);
  //now you can directly use jsonData
}
ET-CS
  • 6,334
  • 5
  • 43
  • 73
  • 1
    When I try and do this, I am getting an error that says `Cannot read property of 'then' of undefined` on the line `activitiesActions.checkUserHosting(theEmail).then(function(data)`. Any idea what this might be and how to fix it? – Surfero Dec 02 '17 at 03:05
  • 2
    did you used `return fetch(...` & `return response.json()...`? – ET-CS Dec 02 '17 at 03:10
  • I forgot to return the call to fetch()... thanks so much for your help! – Surfero Dec 02 '17 at 03:19
  • 1
    Last example is returning a promise anyway, it suppose to return value instead a promise, I did await response.text() and returns another promise, I want the value alone, and this does not work at all. – Máxima Alekz Apr 26 '21 at 09:07
4

You're partially right. It's because you're trying to get the result of this asynchronous call in a synchronous fashion. The only way to do this is the same way you deal with any other promise. Via a .then callback. So for your snippet:

function getActivity() {
    return activitiesActions.checkUserHosting(theEmail).then((jsonData) => {
        // Do things with jsonData
    })
}

Any function that depends on an asynchronous operation must itself become asynchronous. So there's no escaping the use of .then for anything that requires the use of the checkUserHosting function.

CRice
  • 29,968
  • 4
  • 57
  • 70
  • Same as the answer from ET-CS. When I try and do this, I get an error that says `Cannot read property 'then' of undefined`. Why is this happening? – Surfero Dec 02 '17 at 03:07
  • As mentioned in the other answer, return your promise from `checUserHosting`, eg `return fetch...` – CRice Dec 02 '17 at 03:10
2

You can make use of new ES6 and Es7 syntax and what others have written is also correct, but this can be more readable and clean,

you are trying to get aysnc value synchronously, here jsonData will be undefined because, you move to next line of execution before async function(checkUserHosting) is finish executing, this can be written as follows

const getActivity = async () => {
 let jsonData = await activitiesActions.checkUserHosting(theEmail);
  //now you can directly use jsonData
}

and you can write checkUserHosting in a different using new syntax like this

const checkUserHosting = async (hostEmail, callback) => {
 let hostEmailData  = await fetch(`http://localhost:3001/activities/${hostEmail}`)
 //use string literals
 let hostEmailJson = await hostEmailData.json();
 return hostEmailJson;
}
senthil balaji
  • 588
  • 4
  • 18