简体   繁体   中英

How do I make the output of this Javascript API response global?

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);

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

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);
});

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 )

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))
  

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) })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM