Why does my JSON request only work on a click event, and not a page load?

I started working on the weather app, and the first steps I took were to lay out the simple page, add a click function to convert between units, and then obtain the user’s location. After those parts all work, I would work on obtaining the local weather. However, the request to https://ipinfo.io only works on the click event in the app.

I tried initializing variables that store location information and updating the page with the defaults, then after that I have the request made for the user location, and another update for this new information. I have confirmed via simple tests that the update function works as expected, but the function to obtain user location oddly only works on the click event. How do I make this work when the page loads?

I put the jQuery’s $(document).ready function, as well as the standard window.onload function, in hopes that one of them would catch. Although the rest of the code seems to work just fine, so that’s why I am stumped.

Here’s the codepen:

Alternatively, here’s the code:

JS:

  var userip = '';
  var city = '';
  var prov_stat = '';
  var unit = '';
  var weather = '';
  var temp = 0;
 
  function getLocation() {
    $.get("https://ipinfo.io", function(response) {
      userip = response.ip;
      city = response.city;
      prov_stat = response.region;
    }, "jsonp");
  }

  function getLocalWeather() {}
  
  function convertToF(celsius) {
    var fahrenheit;
    fahrenheit = (celsius * (9/5)) + 32;
    return fahrenheit;
  }
  
  function convertToC(fahrenheit) {
    var celsius;
    celsius = ((fahrenheit - 32) * (5/9));
    return celsius;
  }
  
  function convertTemp() {
    var newtemp = 'F';
    if (unit === 'C') {
      newtemp = convertToF(temp);
      unit = 'F';
    } else {
      newtemp = convertToC(temp);
      unit = 'C';
    }
    temp = newtemp;
  }
  
  function updateApp() {
    $('#temp').html(temp +' &deg');
    $('#unit').html(unit);
    $('#location').html(city + ", " + prov_stat);
    $('#weather').html(weather);
  }

  function init() {
    // Initialize variables
    city = 'Vancouver';
    prov_stat = 'BC';
    unit = 'C';
    weather = 'Snow';
    temp = 20;
    
    // Update variables to user's location
    getLocation();
    updateApp();
  }
 
window.onload = function() {
  $(document).ready(function() {
    
    init();

    $('#unit').click(function() {
      getLocation();
      convertTemp();
      updateApp();
    });

  });
}
function init() {
    // Initialize variables
    //city = 'Vancouver';
    prov_stat = 'BC';
    unit = 'C';
    weather = 'Snow';
    temp = 20;
    
    // Update variables to user's location
    getLocation();
     updateApp();
  }

in your init function though you call getLocation first then updateApp
it is not necessary updateApp will called after getLocation .
that’s why when you updateApp called city still is Vancouver

you can try this

function getLocation() {
    
    $.get("https://ipinfo.io", function(response) { 
      userip = response.ip;
      city = response.city;
      prov_stat = response.region;
      updateApp();
    }, "jsonp");
  }

which will make sure when you get json data then you will update

2 Likes

Because your getLocation() function is asynchronous, your code does not work. So basically, to be short, here’s the deal:

  1. The onload event is run.
  2. In your onload listener, you call init.
  3. init calls getlocation.
  4. init calls update app.
  5. getLocation finds the data.

Do you see the problem here? getLocation updates the variables, and updateData updates the DOM. It takes the $.getJson a millisecond or so to get the weather data, but your application does not wait. When you get the data in getLocation, your updateApp function has already run, but the data was empty. In the click event, getLocation has already run and gotten the data because of the onload event. So now, you already have the data set, and you can actually update it.

The easiest fix would be to add a callback after getLocation, and in that callback update the DOM. (Edit: I see this was previously mentioned by @mones-cse!) For more info, I suggest watching this asynchronous tutorial:
http://thenetninja.co.uk/courses/asynchronous-javascript-tutorial

2 Likes

Swift responses!! Thank you! Hopefully all the hair I pulled out will grow back :slight_smile:

Problem solved. Thank you very much IsaacAbrahamson for explaining the order of execution. I had a feeling this was the issue but I was stumped as to how to correct it. Cheers!!