Weather API returns undefined- help please?

I’m working on the weather app, and I’ve had a lot of trouble with it. Right now, I’m just trying to get the basic code to retrieve the weather data to work. I can get the IP lookup to return at least a semi-accurate location, but I can’t use that information to then call the current temperature. I’m trying to store the city and state name in a variable and then pass that into the url for the ajax request. I’ve run the code and looked at the request in dev tools and it’s returning undefined. I don’t know what to try next.

Here is the code:

Thanks all for the help.

Hey there,

The code is returning undefined because location_city, location_state are undefined by the time you make the second AJAX call. You can double check this by using console.log('city: ', location_city).

To be honest, I am not entirely sure why the variables weren’t updated since you defined them outside the first AJAX call. Hope someone can chime in and shed some light on that.

Second, in the case that your variables were properly working inside the second AJAX call, you’re hitting the wrong API endpoint. You want to substitute the part that says ‘geolookup’ with ‘conditions’ once you have access to the city and state.

Here’s some code to help you out some. You can refactor this by extracting the callback functions and just passing them to .done()

jQuery(document).ready(function($) {
  $.ajax({
    url : "http://api.wunderground.com/api/d0d14d4e3688cb90/geolookup/q/autoip.json",
    dataType : "jsonp"
  }).done(function(json) {
    // console.log(json);
    var state = json.location.state;
    var city = json.location.city;
    var requestURL = "http://api.wunderground.com/api/d0d14d4e3688cb90/conditions/q/" + state + "/" + city + ".json";
    // console.log('city: ', city)
    // console.log('state: ', state)
    
    // Here you make another call to the api with the final parameters
    // Notice that the url changes once you have the city and state
    // After your key, instead of 'geolookup' you use 'conditions'
    $.ajax(requestURL, {dataType: "jsonp"}).done(function(resp){
      // handle the final response which includes the weather data
      console.log(resp)
    })
  });
});
1 Like

Hi there – without diving into your code too deeply - it looks like you’re trying to make successive AJAX calls. AJAX is tricky because the code is asynchronus meaning that while the API request is being made the event loop does not stop — ie the rest of your code continues executing.

For instance - it is possible that the first call is made (to get city and province data) and while the browser is working on that the Second call (which uses city and province data) finishes FIRST.

To control the order that these async requests are made you have a couple of options:
-you can use generators
-you can use promises
-you can stick the second call in the “success” portion of the first call (i would write this as its own function so it doesnt get messy)
-you set the calls to async: false (not recommended)

1 Like

Thank you for the response! Yes, I declared the functions outside of the ajax call because I wanted to avoid any scope problems- I’m not sure why they are not working.

What should console.log do when running it on codepen or as a webpage? It doesn’t seem to do anything.

Can you tell me about the .done() function you used in the code? I haven’t seen it in any of the sample code I’ve looked at.

Like @Swoodend explained, AJAX is usually asynchronous, which means the order of execution isn’t linear. As he mentioned, this makes working with AJAX something tricky at first. This explains why the variables are undefined for the second AJAX call.

The .done() function is the same as the success function, just a different syntax. I believe even though both still work, success has been deprecated as of jQuery 3.0.

From the jQuery $.ajax documentation:

Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are removed as of jQuery 3.0. You can use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.

source: jQuery.ajax() | jQuery API Documentation

Edit: Forgot the question about console.log. If you look on Codepen, there’s a tab at the bottom next to where it says ‘Collections’ where you have access to the console. Crucial tool to get to know for debugging JS.

1 Like

I never noticed that was there… That is going to be so helpful, thank you!

I kind of vaguely had an idea that the problem might have something to do with that. None of the solutions you propose are anything I’m familiar with, so I will be exercising my google-fu tonight.

Is there any way to nest the two calls- to make the second ajax call part of the done function?

using the jquery .done() method is using a promise under the hood (I think — havent actually looked). To start you off what if you tried something like this for nesting the second AJAX call?

$ajax.({
  url: 'https://api.com/blahblah',
  dataType: jsonp,
  success: function(data){
     let country = data.country; //get the info you need
     let province = data.province
     makeNextApiCall(country, province);
  }
});

function makeNextApiCall(country, province){
  $ajax.({
    url: 'https://weatherapiurl/' + province + '/' + country
   //etc etc
 })
}
1 Like