-1

I'm trying to make an application to get the recipes from https://edamam.com and I'm using fetch and Request object. I need to make 3 request, and i thought that most beautiful way for do it is make an Object and a method that return the data in JSON. I declarated into constructor a variable called this.dataJson, and i want to save there the data in JSON from the response. For that purpose i use this. The problem is that i have a undefined variable.

.then( data => {this.dataJson=data;
    console.log(data)} )

This is all my code.

class Recipe{
  constructor(url){
    this.url=url;
    this.dataJson;
    this.response;
    
  }
  getJson(){
    var obj;
    fetch(new Request(this.url,{method: 'GET'}))
    .then( response => response.json())
    .then( data => {this.dataJson=data;
    console.log(data)} )
    .catch( e => console.error( 'Something went wrong' ) );
    
  }
  getData(){
    console.log("NO UNDFEIND"+this.dataJson);
  }
  
}
const pa= new Recipe('https://api.edamam.com/search?...');
pa.getJson();
pa.getData();

I'm new studying OOP in JS and more new in Fetch requests... If you guys can help me... Thanks very much!

Javix64
  • 1
  • 1
  • 3
  • 1
    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) – trincot Dec 30 '20 at 17:00
  • 1
    On an online site you press the "Order this pizza" button, and then look surprised when your plate is still empty. You cannot expect a future result to be available now. Check the suggested link for more information and how to get it done *asynchronously* – trincot Dec 30 '20 at 17:01

1 Answers1

0

Here's a solution using async-await (and a placeholder API):

class Recipe {
  constructor(url) {
    this.url = url;
    this.dataJson;
    this.response;

  }
  // the async keyword ensures that this function returns
  // a Promise object -> we can use .then() later (1)
  async getJson() {
    try {
      const response = await fetch(new Request(this.url, {
        method: 'GET'
      }))
      const json = await response.json()
      this.dataJson = json
    } catch (e) {
      console.error('Something went wrong', e)
    }
  }
  getData() {
    console.log("NO UNDFEIND:", this.dataJson);
  }

}
const pa = new Recipe('https://jsonplaceholder.typicode.com/todos/1');
// 1 - here we can use the "then", as pa.getJson() returns
// a Promise object
pa.getJson()
  .then(() => {
    pa.getData()
  });

If we want to stay closer to your code, then:

class Recipe {
  constructor(url) {
    this.url = url;
    this.dataJson;
    this.response;

  }
  getJson() {
    // var obj; // not needed
    // the "fetch" always returns a Promise object
    return fetch(new Request(this.url, { // return the fetch!
        method: 'GET'
      }))
      .then(response => response.json())
      .then(data => {
        this.dataJson = data;
        // console.log(data) // not needed
      })
      .catch(e => console.error('Something went wrong'));

  }
  getData() {
    console.log("NO UNDFEIND:", this.dataJson); // different syntax here
  }

}
const pa = new Recipe('https://jsonplaceholder.typicode.com/todos/1');

// using "then", because the "fetch" returned a Promise object
pa.getJson()
  .then(() => {
    pa.getData();
  });

The problem with your original code is that you initiate the request (pa.getJson()) and then immediately (on the next line) you want to read the data (pa.getData()). pa.getData() is called synchronously (so it happens in milliseconds), but the request is asynchronous - the data needs time to arrive (probably hundreds of milliseconds) - so, it's not there when you try to read it (it simply hasn't arrived yet).

To avoid this you have to use a technique to handle this asynchronous nature of the request:

  • use a callback function (blee - so last decade)
  • use a Promise object with then() (much better) or async-await (yeee!)

and call the pa.getData() when the response has arrived (inside the callback function, in the then() or after awaiting the result).

muka.gergely
  • 8,063
  • 2
  • 17
  • 34