Search code examples
javascriptxmlhttprequestundefined

Unable to get the same results with 2 pieces of somewhat similar XMLHttpRequest


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.


Solution

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