Hope you are able to help or just help me understand why I have 2 almost similar codeblocks where one does not do what I expect.
I am trying to make some API calls where I populate a variable with the data that is pulled from the API call. In the first there is no problem at all, but the second I can't populate the variable. I have tried googling the problem and it seems to be because of the asynchronous nature of XmlHttprequests. But again, I do not get why one solutions works and another don't.
The solution that work:
// Get JSON and convert it to an object
var obj;
const Http = new XMLHttpRequest();
const url = "https://type.fit/api/quotes";
Http.open("GET", url);
Http.send();
Http.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
obj = JSON.parse(Http.responseText);
}
};
In this solution I am able to get the data and populate the variable obj and use it globally.
link to the solution: https://codepen.io/Kfriis/pen/QWjGZmx
The solution that don't work:
//function that takes a currency in capital letters and returns
var rates;
var currency = 'gbp';
const currencyString = currency.toUpperCase();
const API = "api.frankfurter.app"
const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`
const http = new XMLHttpRequest();
http.open("GET", URL);
http.send();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
}
};
console.log(rates)
This do, for some reason, not work. I do not get why the rates variable do not get populated since the request is basically the same for the first code snippet. I have come down to an idea of it being because the data sent from the 2 API endpoints may be different in some way. Because if it was only because of the asynchronous requests, both code snippets should return undefined.
Link https://codepen.io/Kfriis/pen/VwvpKmd
I do hope someone is able to shine some light on this. I must be doing something wrong in the second snippet, because I can console.log() from inside the onreadystatechange but not outside it. Which led me to believe for a long time that it was a scoping issue.
Your code does work. However, you're logging console.log(rates)
outside the http.onreadystatechange
-function which means you're logging the rates before you get the response. If you change the code block
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
}
};
console.log(rates)
to
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
console.log(rates)
}
};
it should work.
Here's a working example code if you wanna add the code to a function.
// Function that takes a currency in capital letters and returns
function getCurrencyRates(currency, cb) {
const currencyString = currency.toUpperCase();
const API = "api.frankfurter.app"
const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`
const http = new XMLHttpRequest();
http.open("GET", URL);
http.send();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
cb(JSON.parse(http.responseText));
}
};
}
// Call the function and pass "gbp" as currency.
// Rates will be logged in response.
getCurrencyRates('gbp', function(response) {
console.log(response);
});