0

I have following code to get weather details of cities. When I load the page, It is providing correct weather details of given cities by URL get method. But can't print the city name of each result. In my example, It always says "Sydney"

How can I print each city name with the result?

Code:

x = window.location.search.substr(6);
y = x.split("%2C");

$(document).ready(function() {
  $('#b1').click(function() {

    for (i = 0; i < y.length; i++) {

      city = y[i];

      $.ajax({
        url: 'http://api.openweathermap.org/data/2.5/weather?q=' + city +
          "&units=metric" +
          "&appid=ace585585ed8eb42338b8e663fe0170e",
        type: 'get',
        dataType: 'jsonp',
        success: function(data) {
          var w = showd(data);
          var para2 = $("<p></p>").text(city);
          var para = $("<p></p>").text(w);
          $("body").append(para2, para);
        }
      });

      function showd(data) {
        return data.weather[0].description;

      }
    }
  });
});

$(document).ready(function() {
  document.getElementById("b1").click();
});
<Script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></Script>

<button style="visibility:hidden;" id="b1">Click</button><br><br>
<p id="data"></p>
<p id="p2"></p>

URL:

file:///C:/wamp/www/aTravelz/checkweather.html?wthr=Moscow%2CLondon%2CColombo%2CSydney

Result:

Sydney

overcast clouds

Sydney

light intensity shower rain

Sydney

few clouds

Sydney

broken clouds
Master Yoda
  • 4,334
  • 10
  • 43
  • 77
Dean Johns
  • 498
  • 4
  • 28
  • Spend some time reading [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) – Gabriele Petrioli Nov 30 '17 at 13:21

1 Answers1

1

Your code is using last value of city (after the for-loop has been completed) will be used since AJAX response will come after the same.

You need to lock the value of city for each AJAX request

 (function(city){ $.ajax({
           //rest of the ajax code stays as is
 }))(city);

Or you can use let instead of var as @xander said in the comments (as shown in demo as well)

Demo

var arr = [ 1,2,3 ];
for( var counter = 0; counter < arr.length; counter++ )
{
   let c = arr[ counter ];
   setTimeout( function(){
      console.log(c)
   }, 100);
}
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • It should also work if the city variable is scoped to the for-block, e.g. with `let city = y[i]` when using ES6. – xander Nov 30 '17 at 13:22
  • @xander AJAX call will still be inside the for-loop so it will still have the access to the `city`. – gurvinder372 Nov 30 '17 at 13:24
  • yes but the success closure will capture a different `city` variable with every ajax-request when defined with `let` instead of `var`, so it should work if I'm not mistaken. – xander Nov 30 '17 at 13:28
  • @xander `city` will still be block scoped and AJAX call will fall under the same block, isn't it? – gurvinder372 Nov 30 '17 at 13:29
  • @xander is correct about `let` in `for` loop. Op's use of globals is not good either way – charlietfl Nov 30 '17 at 13:31
  • @xander You are right, I tested as well. – gurvinder372 Nov 30 '17 at 13:38
  • 1
    @gurvinder372 yeah it's a little mind bending at first, but for me the `var` keyword is worse because it scopes the variable to the function, not the block you define it in (like `let` does). – xander Nov 30 '17 at 13:46