Ad

Unable To Get The Same Results With 2 Pieces Of Somewhat Similar XMLHttpRequest

- 1 answer

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.

Ad

Answer

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);
});
Ad
source: stackoverflow.com
Ad