0

I'm working on a homework project to use an API to display the weather. Originally, I declared variables "latty" and "lonny" at the top of my script, in the a main function scope everything else was inside, and later they were set = to latitude and longitude using navigator.geolocation. After setting them to the coordinates I then tried to use them as part of the URL line that is sent to the API, but the values for latty and lonny never carried over. I thought declaring them in the parent function would allow them to be used in subsequent, nested functions. Since geolocation requires a function in order to get coordinates, I ended up having to nest the entire script within the getPosition() function in order to be able to use the values that it retrieves:

this.addEventListener("load", navigator.geolocation.getCurrentPosition(getPosition));

function getPosition(position) {
  var latty = position.coords.latitude;
  var lonny = position.coords.longitude;
  var url = "https://api.darksky.net/forecast/";
  var apiKey = '5a4ae697ea6b02e5a4ae697ea6b02e/';

weatherAjax();

function weatherAjax(){
$.ajax({
  url: url + apiKey + latty + "," + lonny + degreeType,
  dataType: 'jsonp',
  success: function(data) {
    $("#weatherID").html("<h1>" + Math.round(data.currently.temperature) + degreeSymbol + data.currently.summary + "</h1>");
  }
}); 
}

Is there a better way to do this, without nesting everything within getPosition()? It seems strange that I cannot get information from geolocation, set those coordinates to a variable, and call them into another function. I couldn't figure out how to return that information, either, and I won't share that mess with you here because it was terrible.

I understand the basic idea of scope as: you can only access variables that are "higher up" in the nesting order. Sibling-level or child functions will not "share" variable access. Is this correct? Can this be improved upon?

2
  • It sounds like you may be confusing function scope with synchronous and asynchronous code. Since you have working code, this isn't entirely a duplicate. But the answers you're looking for are probably here: stackoverflow.com/questions/14220321/…
    – David
    Commented Jun 3, 2017 at 0:37
  • 1
    getCurrentPosition() is asynchronous. So you can't access the data until it has been received. It's the same as trying to eat a pizza that hasn't been delivered yet
    – charlietfl
    Commented Jun 3, 2017 at 0:37

1 Answer 1

1

There's a few issues with your script.

First of all, navigator.geolocation.getCurrentPosition(...) returns undefined, so you're not actually attaching an event handler to the page load event, and that call to addEventListener() does nothing and fails silently.

Secondly, there is a better way of organizing the script so that you don't have to nest your script in the getPosition() callback. Use function parameters:

navigator.geolocation.getCurrentPosition(getPosition);

function getPosition(position) {
  var latty = position.coords.latitude;
  var lonny = position.coords.longitude;
  var url = "https://api.darksky.net/forecast/";
  var apiKey = '5a4ae697ea6b02e5a4ae697ea6b02e/';

  weatherAjax(latty, lonny, url, apiKey);
}

function weatherAjax(latty, lonny, url, apiKey) {
  $.ajax({
    url: url + apiKey + latty + "," + lonny + degreeType,
    dataType: 'jsonp',
    success: function (data) {
      $("#weatherID").html("<h1>" + Math.round(data.currently.temperature) + degreeSymbol + data.currently.summary + "</h1>");
    }
  }); 
}

So, finally, if you want this to actually run after the page loads, throw all of that into an anonymous callback to load:

window.addEventListener('load', function () {
  // everything above goes in here
});

All together, you get this:

window.addEventListener('load', function () {

  navigator.geolocation.getCurrentPosition(getPosition);

  function getPosition(position) {
    var latty = position.coords.latitude;
    var lonny = position.coords.longitude;
    var url = "https://api.darksky.net/forecast/";
    var apiKey = '5a4ae697ea6b02e5a4ae697ea6b02e/';

    weatherAjax(latty, lonny, url, apiKey);
  }

  function weatherAjax(latty, lonny, url, apiKey) {
    $.ajax({
      url: url + apiKey + latty + "," + lonny + degreeType,
      dataType: 'jsonp',
      success: function (data) {
        $("#weatherID").html("<h1>" + Math.round(data.currently.temperature) + degreeSymbol + data.currently.summary + "</h1>");
      }
    });
  }

});
1
  • Thanks for pointing out. I had used setTimeout without realising it might actually take more than 2s delay at some point since it had never failed to do so. I changed my code according to your answer.
    – Ozan
    Commented Jun 3, 2017 at 2:10

Not the answer you're looking for? Browse other questions tagged or ask your own question.