0

I tried to fetch some information through a API and it worked. The next step was to define "ourserver" with the right server data. So I made a foreach and I console-logged just server and got the right one, but if I try to define ourserver = server; the last console log is showing me that ourserver is still undefined.

let ip = "myserverip";
let ourserver;

const fetchPromise = fetch('http://myapi.com/list/servers')
fetchPromise.then(response => {
  return response.json();
}).then(list => {
  list.forEach(function (server) {
    if (server.host === ip) {
      ourserver = server;
      // console.log(server); this was defined

    }
  });
});

console.log("daten: " + ourserver); // this is after all still undefined
Uuuuuumm
  • 608
  • 5
  • 21
MisterLA
  • 91
  • 1
  • 8

3 Answers3

1

read more about Async JS and promise, the reason for this that

  • fetch promise will run
  • it's an async operation so the interpreter will not wait until it finish so he will continue execution for the rest of the file.
  • it will print the console.log
  • and if the async operation finished the call back will be put in something called event queue, and if the call stack is empty, the event loop will execute your callback function which be the function inside .then in your case.
Abdelrahman Hussien
  • 505
  • 2
  • 4
  • 17
1

The reason you are seeing this issue is because your code to define ourserver actually occurs after your console.log("daten: " + ourserver);, you can prove this to yourself by logging the date, too:

ourserver = server;
console.log(server, new Date());
...
console.log("daten: " + ourserver,new Date());

You will see the daten console.log occurs before your log of server.

When you call fetch, it will perform the fetching in the background, and once it has completed, it will call the function provided to then. This is how asynchronous programming works in JavaScript.

Your code that requires ourserver to be present should happen in your then.

Here's your code modified to show how I would go about this:

const ip = "myserverip";

fetch('http://myapi.com/list/servers').then(response => {
    return response.json();
}).then(list => {
    return list.find(server => server.host === ip);
}).then(ourserver => {
    console.log("daten: " + ourserver);
});

If you absolutely must access the value of ourserver outside of the fetch, this can be achieved one of two ways. One way is to define a callback, and the other way is to wait for the value to be set. Here are both ways:

callback

const ip = "myserverip";
let ourserver = null;
const callback = () => {
    console.log(ourserver);
}

fetch('http://myapi.com/list/servers').then(response => {
    return response.json();
}).then(list => {
    ourserver = list.find(server => server.host === ip);
    callback();
});

wait

const ip = "myserverip";
let ourserver = null;

fetch('http://myapi.com/list/servers').then(response => {
    return response.json();
}).then(list => {
    ourserver = list.find(server => server.host === ip);
});

const check = () => {
    if(ourserver == null){
        return setTimeout(check,100);
    }
    
    console.log(ourserver);
};

check();

I do not recommend using the wait and check solution.

Kyle
  • 3,935
  • 2
  • 30
  • 44
  • Will try it but what if i want to use ”ouserver” outside of the fetch function? – MisterLA Aug 11 '20 at 20:59
  • The only way you can use it outside the fetch function is if you know that it is set before trying to use it. I've updated my answer with an incredibly awful hack that I do not recommend you do. – Kyle Aug 11 '20 at 21:07
  • So the Callback would be the one you would recommend instead of the wait and check? – MisterLA Aug 11 '20 at 21:11
1

let ip = "myserverip";
let ourserver;

async function fetchPromise(){
try{
const response = await fetch('http://myapi.com/list/servers');
const list =  await response.json();
list.forEach((server) => {
    if (server.host === ip) {
      ourserver = server;
    }
  });
console.log("daten: " + ourserver);
}catch(e){
console.log(e);
}
}

You can make use of async/await to handle the fetch better and for a cleaner code. This way you gonna wait until you get the response from the fetch api and then you will have the value of ourserver available.

Ram Sankhavaram
  • 1,218
  • 6
  • 11