0

In the below code why am I getting a in the last line as undefined? How do I write to get response in variable a

function getData(){
const url = "https://jsonplaceholder.typicode.com/users";
url2='https://jsonplaceholder.typicode.com/posts/'
fetch(url).then((res) =>{
  res.json().then((dataAsJson) => {
    return(dataAsJson[0].id);
  })
  .then((id)=>{
     fetch(url2+"/"+id).then((res)=> {
     return res.json().then((data) => {
      return(data);
    })
    })
})

})
}


var a = getData();
console.log(a)```
user3595524
  • 51
  • 1
  • 6
  • Does this answer your question? [How to return value from an asynchronous callback function?](https://stackoverflow.com/questions/6847697/how-to-return-value-from-an-asynchronous-callback-function) – Tân Aug 16 '20 at 06:44

3 Answers3

1

You are missing two return statements to actually pass the values from one promise to the next. So to make your code work, you have to include them:

async function getData(){
  const url = "https://jsonplaceholder.typicode.com/users";
  url2='https://jsonplaceholder.typicode.com/posts/'
  const data = await fetch(url).then((res) =>{
    return res.json().then((dataAsJson) => {
      return(dataAsJson[0].id);
    })
  .then((id)=>{
     return fetch(url2+"/"+id).then((res)=> {
        return res.json().then((data) => {
          return(data);
        })
      })
    })
  })
}

One more tip here: When returning from a promise, it doesn't matter if it is another promise or a simple value - the next then call will always get the unwrapped value. So you actually don't have to nest all those promise calls. It would be way more readble if you put it like this:

const url = "https://jsonplaceholder.typicode.com/users";
url2='https://jsonplaceholder.typicode.com/posts/'
const data = await fetch(url)
  .then((res) =>{ return res.json()})
  .then((dataAsJson) => { return(dataAsJson[0].id); })
  .then((id)=>{ return fetch(url2+"/"+id); })
  .then((res)=> { return res.json(); })

And also: Since you are just returning one value in each callback, you can make use of the JavaScript-Arrow-Function functionality that automatically returns if there is only one expression and short it even more to this:

const url = 'https://jsonplaceholder.typicode.com/users';
url2 = 'https://jsonplaceholder.typicode.com/posts/';
const data = await fetch(url)
  .then(res => res.json())
  .then(dataAsJson => dataAsJson[0].id)
  .then(id => fetch(`${url2}/${id}`))
  .then(res => res.json());

That is better readable and errors are easier to spot. :)

Update: I totally overlooked that in your code, your are trying to read synchronsouly from the asynchronous getData() function. @the spectre cleared that up in his answer - so this should be the accepted one. However, to not let a wrong code stand, I edited the correct behaviour into my answer.

David Losert
  • 4,652
  • 1
  • 25
  • 31
0

You should be able to streamline that function with the use of await. It removes the need for nested callbacks. This code isn't tested but should in theory work.

async function getData() {
  const url = "https://jsonplaceholder.typicode.com/users";
  const url2 = "https://jsonplaceholder.typicode.com/posts/";

  const firstFetch = await fetch(url)
  const firstResult = await firstFetch.json();

  const id = firstResult[0].id;

  const secondFetch = await fetch(url2 + "/" + id)
  return await secondFetch.json();
}

https://javascript.info/async-await

You could alternatively create a new promise to resolve in your second fetch. But this approach is messier

Lex
  • 4,749
  • 3
  • 45
  • 66
  • [https://repl.it/repls/UntruePitifulSystemsanalysis] I tried to use this...but its returning me pending promise..How do I counsume this? – user3595524 Aug 16 '20 at 07:06
0

Since you're not returning anything from getData() you're getting undefined.

Promises and their chained methods, then() and catch will return an instance of Promise themselves, not the data you're returning from the callback in then().

To get the behavior you're expecting, one way is to use async and await. Piggybacking off of David, you'd do:

const url = 'https://jsonplaceholder.typicode.com/users';
const url2 = 'https://jsonplaceholder.typicode.com/posts/';
const data = await fetch(url)
  .then(res => res.json())
  .then(dataAsJson => dataAsJson[0].id)
  .then(id => fetch(`${url2}/${id}`))
  .then(res => res.json());
  
console.log(data);
the spectre
  • 350
  • 4
  • 11