1

I have a fetch request that POSTs to express and then captures a response (and data) from express using '.then'. I want to be able to pass the resulting JSON object to another component as an export/import but am unable to do so as the returned data is not accessible outside of '.then'. Here's the issue I'm running into:

fetch("http://localhost:5000", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(newUser),
})
  .then(function (response) {
    return response.json();
  })
  .then(function (data) {
    var currentUser = data;
    console.log(currentUser);//<---JSON object
  });

  console.log(currentUser);//<---undefined - Why?

Returning currentUser has not resolved this issue. Any assistance is greatly appreciated:)

Omar Haqqani
  • 41
  • 1
  • 3
  • 2
    It should behave like that because of scoping, try to assign that value to some variable which is declared in the parent function or you can choose a global variable. – devd Aug 07 '20 at 19:01

1 Answers1

0

The currentUser variable is out of scope in your example, the .then {} block has its own scope that does not extent to its parent. If you declared your variable above your fetch block it would be available later, but execution will most likely reach your second console.log before the promise is returned as the fetch is an asynchronous process. You have to await the response for the variable to have its contents.

Welcome to the complex world of asynchronous programming! Here are some resources about asynchronous programming https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous

var myId = 12345;
var id;
console.log("Fetching info on " + myId);

fetch("https://exampleapi.org/getjson.php?id=" + myId)
  .then(
    (successResponse) => {
      if (successResponse.status != 200) {
        console.log("failed to get a 200 response code");
        return null;
      } else {
        return successResponse.json();
      }
    },
    (failResponse) => {
      console.log("failed to get a response");
      //exit;
      return null;
    }
  )
  .then((data) => {
    if (data.id && data.id > 0) {
      console.log('In Block', data.id);
      id=data.id
    }
  });

console.log('First Try', id);

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedGreeting() {
  console.log('Second Try', id);
  await sleep(2000);
  console.log('Finally!!!', id);
}

delayedGreeting();
console.log('Third try', id);

console.log might then be: (assuming the data has been received 2000ms after request)

"Fetching info on 12345"
"First Try" undefined
"Second Try" undefined
"Third try" undefined
"In Block" 12345
"Finally" 12345

Due to network congestions or something, it is possible "Finally" would also be undefined. Can you have your code follow down the promise chain as that is what these programming constructs are attempting to solve...?

  • Note that this is an extremely common issue on Stack Overflow. It may be worth your while to do a little search for similar questions before putting too much effort into answering. – Heretic Monkey Aug 07 '20 at 19:49
  • Thank you, this is very helpful! I'm going to go through the resources you provided and update shortly! Your help is much appreciated. – Omar Haqqani Aug 07 '20 at 22:01
  • UPDATE: Sorry for the late response here. Declaring currentUser at the top of the file (outside the functional component) allowed me export for use in other components. Also, restricting manipulation of the fetch response data to within the .then block prevented any "scope" issues. Thanks for the guidance. – Omar Haqqani Aug 21 '20 at 14:11