0

How can I use an object outside of a function that utilizes .fetch and promises?

If I have:

getBuildList();

function getBuildList(){
  fetch('http://127.0.0.1:8000/builds/buildStatsAPI')
    .then(function(res){
      return res.json();
    })
    .then(function(data) {
      initialLoad(data);

    })
    .catch(function(err){
      console.log(err);
    });
}

I want to use data outside of this functions scope.

I have tried to add return data pretty much everywhere inside this function, but cannot seem to make it available outside the scope of this function. Ideally I only want to fetch this data once from the API, then re-use the fetched data with different functions when buttons are pressed on the DOM.

I have tried (among many others):

getBuildList();
let jsonData = getBuildList();
console.log(jsonData); //expecting data from fetch. but returns undefined

function getBuildList(){
  fetch('http://127.0.0.1:8000/builds/buildStatsAPI')
    .then(function(res){
      return res.json();
    })
    .then(function(data) {
      initialLoad(data);
      let myData = data;
      return myData;

    })
    .catch(function(err){
      console.log(err);
    });
}
MattG
  • 1,682
  • 5
  • 25
  • 45
  • 2
    Make sure you return the promise.. `return fetch(....`, and then from outside,, either `getBuildList().then(...` or `await getBuildList()` – Keith Feb 08 '19 at 10:27
  • Refer : [Using fetch() and a new Promise object to get API results](https://codereview.stackexchange.com/questions/123577/using-fetch-and-a-new-promise-object-to-get-api-results) for better way to do. – Şivā SankĂr Feb 08 '19 at 10:32
  • 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) – adiga Feb 08 '19 at 10:38

2 Answers2

4

Just return the promise:

function getBuildList(){
  // (note the "return" below, otherwise result will be undefined.
  return fetch('http://127.0.0.1:8000/builds/buildStatsAPI')
    .then(function(res){
      return res.json();
    })
    .then(function(data) {
      initialLoad(data);
      let myData = data;
      return myData;

    })
    .catch(function(err){
      console.log(err);
    });
}

Then consume the result using .then:

getBuildList().then(function(jsonData){
    // use jsonData here.
}).catch(function(error){
    // Handle the error here.
});

EDIT: To store the result in a global variable, edit the last piece of code as follow:

var jsonData = null; // <-- global variable
getBuildList().then(function(res){
    jsonData = res;
}).catch(function(error){
    // Handle the error here.
});

Example to consume data on click (after ensuring the above function is called)

function consumeData() {
   if (jsonData) { // <-- this will assert jsonData is truthy, meaning it's not null or undefined, in that case.
       // consume jsonData here. Remember that changing jsonData will change it GLOBALLY!.
   }
   else {
       // OOOPS, jsonData may either be not yet defined or may just be null or empty due to a misleading or wrong fetch response.
   }
}
briosheje
  • 7,356
  • 2
  • 32
  • 54
  • Also handle your promise error `.catch(function(err){console.log(err);});` – Şivā SankĂr Feb 08 '19 at 10:41
  • @ŞivāSankĂr I've copy-pasted the OP's code, he should handle the error accordingly in the getBuildList function. The external .catch is needed if any exception occurs in the getBuildsList() promise callback. – briosheje Feb 08 '19 at 10:43
  • @briosheje thanks for the response. How would I consume the data in other functions. Meaning, if a button is pressed in the DOM, I would like to call a function that consumes the jsonData. Essentially make it available to the global scope – MattG Feb 08 '19 at 10:50
  • @MattG just call the function providing **jsonData** as an argument. Is the getBuildList function called **after** the button is clicked? – briosheje Feb 08 '19 at 10:51
  • The button is pressed after the getBuildList function is called. I will try your suggestion – MattG Feb 08 '19 at 10:52
  • @MattG then store jsonData in a global variable (outside of the callback) and get it once the button is clicked. BEWARE THOUGH: make sure the button is clickable **only after getBuildList** is finished. – briosheje Feb 08 '19 at 10:53
  • @briosheje thank you, I will ensure it can only be pressed after getBuildList is finished. I'm unsure of how to store it in a local variable though. Sorry these promise functions have me confused... – MattG Feb 08 '19 at 10:57
  • 1
    @MattG I will edit my question above to show you how to store it in a global variable instead – briosheje Feb 08 '19 at 10:58
2

Maybe async/await syntax will be easier to understand for you.

async function getBuildList(){
  const response = await fetch('https://pokeapi.co/api/v2/pokemon/ditto/');
  return response.json();
}

(async () => {
  const data = await getBuildList();
  console.log(data)
})()
dporechny
  • 638
  • 5
  • 12