Reputation: 11
I'm trying to receive the output for the following code where the cc variable would log a value into the empty global country variable. Afterwards print it to the console, however it isn't working. How would I make the local variable cc here to global/give the global variable country a value?
var country = '';
fetch('https://extreme-ip-lookup.com/json/')
.then( res => res.json())
.then(response => {
var cc = (response.countryCode);
country = cc;
});
console.log(country);
Upvotes: 0
Views: 972
Reputation: 33439
fetch
returns a Promise
, hence the .then()
chain in your question.
But if you stepped into Promise Land, you won't find out. You'll have to do everything with Promises.
But you might split you logic into small manageable parts like here
console.clear()
let cached = null;
const lookup = () => fetch('https://extreme-ip-lookup.com/json/');
// Caching json and not the fetch promise, because
// https://stackoverflow.com/a/54731385/476951
const getJson = () => cached = cached || lookup() .then(response => response.json());
const getParameter = (parameter) => getJson() .then(json => json[parameter]);
const getCountry = () => getParameter('country') .then(value => value);
const getCountryCode = () => getParameter('countryCode') .then(value => value);
getCountryCode().then(countryCode => {
console.log('countryCode:', countryCode)
})
getCountry().then(country => {
console.log('country:', country)
})
getParameter('city').then(city => {
console.log('city:', city)
})
Upvotes: 0
Reputation: 21130
The problem with your currently call console.log(country)
before country
is set to response.countryCode
.
You could solve this by placing your code inside an async IIFE in the following manner:
(async () => {
const response = await fetch('https://extreme-ip-lookup.com/json/');
const ipData = await response.json();
const country = ipData.countryCode;
// place all code that uses `country` in here
console.log(country);
})();
If you have another script with function definitions that depends on county
be sure to accept it as parameter and don't pull the data from a global variable.
// helper_functions.js
// Bad
function someFunctionThatUsesCountry() {
console.log(country); // <- don't expect the global to be set
}
// Good
function someFunctionThatUsesCountry(country) {
console.log(country); // pull country ^ from the parameter list
}
You can then call you other script inside the IIFE by just passing the value.
(async () => {
// ...
someFunctionThatUsesCountry(country);
})();
If for some reason want a global variable really bad. You should place the promise inside this variable, not the value. With this promise you can pass the value, as well as notify other scripts when this value is available.
// script_1.js
window.country = fetch('https://extreme-ip-lookup.com/json/')
.then(response => response.json())
.then(ipData => ipData.countryCode);
// script_2.js (must be loaded after script_1.js)
window.country.then(country => { // <- wait until country is available
// do stuff with country
console.log(country);
});
Upvotes: 1
Reputation: 5863
console.log
is happening before fetch
is resolved. Try this:
let country = '';
fetch('https://extreme-ip-lookup.com/json/')
.then(res => res.json())
.then(res => country = res.countryCode)
.then(() => console.log(country))
Upvotes: 0
Reputation: 136
Your problem come from the fact that your fetch is an asynchrone function, with a promise.
What you want to do is that (I suppose)
var country = '';
//then
fetch('https://extreme-ip-lookup.com/json/')
.then( res => res.json())
.then(response => {
var cc = (response.countryCode);
country = cc;
});
//then
console.log(country);
But, since you use an async function, this is what is done:
//first
var country = '';
//second
fetch('https://extreme-ip-lookup.com/json/')
.then( res => res.json())
.then(response => {
//fourth
var cc = (response.countryCode);
country = cc;
});
//third
console.log(country);
How to fix that? it depend. If your console.log is triggered by a button, make it wait for country to be filled
else, put your code in the last then, or use Promise.all()
(documentation here)
Upvotes: 0
Reputation: 793
It seems like your problem has to do with the asynchronous nature of your code. Let me explain.
var country = '';
fetch('https://extreme-ip-lookup.com/json/')
.then( res => res.json())
.then(response => {
var cc = (response.countryCode);
country = cc;
});
console.log(country);
The fetch function is asynchronous. That's why you need the .then
methods. This means that while the fetch function runs, JavaScript doesn't stop the rest of the program, and instead moves on while fetch()
runs in the background. Hence, when you console.log(country)
, it's still of the original value (empty string).
To answer your question, you can use Promise
s to log the value of cc.
var country = '';
const fetchPromise = fetch('https://extreme-ip-lookup.com/json/')
.then( res => res.json())
.then(response => {
var cc = (response.countryCode);
country = cc;
});
Promise.resolve(fetchPromise) // Waits for fetchPromise to get its value
.then(() => console.log(country))
You can find out more about promises at the MDN docs
Upvotes: 1