Show the Local Weather - FCC Weather API

Here’s my code so far(which is basically what the fcc challenge provides):

$(document).ready(function() {
if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(function(position) {
    $("#data").html("latitude: " + position.coords.latitude + "<br>longitude: " + position.coords.longitude);
  });
}
}); 

I don’t understand how to use the information provided here: https://fcc-weather-api.glitch.me/ and also this “Many internet browsers now require an HTTP Secure (https://) connection to obtain a user’s locale via HTML5 Geolocation. For this reason, we recommend using HTML5 Geolocation to get user location and then use the freeCodeCamp Weather API https://fcc-weather-api.glitch.me which uses an HTTP Secure connection for the weather. Also, be sure to connect to CodePen.io via https://.”. Can somebody help?

Http secure (https) is a secure version of http. Codepen only uses https and will only work with https. That is OK, because geolocation and the fcc weather api also use https so everything will work.

In codepen, something like:

$(document).ready(function() {
  
  var url = "https://fcc-weather-api.glitch.me/api/current?lat=35&lon=139";
  $.getJSON(url, function(data) {
    console.log("weather data:", data)
  });
  
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      console.log('position data:', position)
    });
  }
 
}); 

will output the location and a sample weather data to your console (ctrl-shft-j to open). Don’t forget to load jQuery in settings/javascript/quick-add. This should get you started. You’ll have to do some rearranging to get this right, but it’s a start. I don’t want to give too much away.

Let us know if this doesn’t help or if you get stuck again.

This my Pen so far: https://codepen.io/GiaFil/pen/jzxvXZ
In the console, I get errors saying that position isn’t defined. Isn’t it being defined by the URL that is passed in?

That is correct. That’s because position is defined by the call to geolocation. Anything that refers to position must be inside the callback to geolocation, where console.log('position data:', position) is. This is because it is asynchronous. This is a hard concept to get in JS but is extremely important (and useful) in JS. Try putting the getJSON call inside the geolocation callback.

Here’s an old pen I wrote for people having this confusion and here’s something I wrote for someone having a similar problem. The example uses $.ajax but will work fine for $.getJSON.


I think that one thing you are not understanding is asynchronicity. You have two asynchronous functions in your code, the call to navigator.geolocation.getCurrentPosition and your ajax call.

These functions are requesting data and not waiting for an answer before they go on to the next code. The most basic way to handle this is with callback functions. You use a callback function in your ajax call (the success function) and you use one for you navigator call (showPosition). What these are saying are "go ahead and finish the rest of the program and just I’ll just call back to this callback function once I get my data back.

You have two asynchronous operations, one that depends on the other. The most basic way to handle that is to next them inside each other. So, I might have something like:

navigator.geolocation.getCurrentPosition(function(position) {
  // manipulate variables if needed
  $.ajax({
    url:
      "https://fcc-weather-api.glitch.me/api/current?lat=" + position.coords.latitude + "&lon=" + position.coords.longitude,
   success: function(data) {
     // use data object and send it to the screen
   });
});

Does that make sense? The ajax call must be inside (or called from inside) the callback to the navigator call or the variable won’t be defined yet. In your original code, you get to the ajax call before navigator gets back so it doesn’t know what those variables are.

The whole asynchronous thing is extremely important in JavaScript. Most languages are synchronous (you execute in piece of code at a time and wait for it). Because JS utilized so many asynchronous resources, this would be inefficient. So, JavaScript is asynchronous, which is why you use so many callback functions, to deal with the asynchronicity.

I think you could get rid of some of those functions. Or you could use them in place of your anonymous callbacks - it’s a stylistic choice but in the beginning I found writing directly in an anonymous callback to be clearer.

Another observation: When you define your url string, you have “&&lon=” - there should be only one ampersand.

Let us know if any of this is confusing.


1 Like

I implemented your suggestion and position is no longer undefined. But I’m not sure where to put a console.log(data) in my code, so I can get the data I need to go forward.

Inside your success function.

   success: function(data) {
     // use data object and send it to the screen
    console.log(data); 
    }

I tried that before but I got nothing on the console…

Try it now after you made your other changes. I put it in your code and it works fine for me.

It doesn’t really work for me. It did once but it was way too asynchronous. I’m a bit confused…

I just loaded your Codepen and get the following in the console (my local weather).

I am getting the data sometimes I reload but very few. I don’t know if there’s something wrong with my connection or something…

It looks like you are using navigator.geolocation. I have seen some issues with codepen (maybe not specific to codepen, but that’s where I’ve seen it) where it will run find and then stall on subsequent calls. There are two solutions. 1) Use an API like ip-api.com to get location. 2) Hardcode the lon and lat in for now and add it in later.

I send codepen a message. We’ll see what they say.

Both solutions don’t seem to work. The second same result as before and for the first CodePen needs the API to use HTTPS. I’m lost. Can you at least verify if my code is correct, so I can (in theory at least) move forward?

Then find a different API. A google search found freegeoip:

$.getJSON('https://freegeoip.net/json/?callback=?', function(data) {
  console.log('lat:', data.latitude);
  console.log('lon:', data.longitude)
});

I managed to get it to work. I just needed to wait a bit to get the data every time I made a change but eventually, I added all the functionality that was required to complete the challenge. Thanks for your time.