Reputation: 333
I am using the code below to retrieve the latitude and longitude of a given location if the value has been changed for each div containing the class .event
.
The problem I'm having is that only two outcomes occur from this code:
lat
and lon
variablelat
and lon
remain exactly the same, as if they were remain untouched so the JSON values are not replaced.Below is the code I am using:
$(".button").click(function(){
data = "";
$(".event").each(function(){
original = $(this).find(".address").data("original");
location = $(this).find(".address").html();
lat = $(this).find(".lat").html();
lon = $(this).find(".lon").html();
if (original !== location) {
$.getJSON( "http://nominatim.openstreetmap.org/search?q="+location+"&format=json&polygon=1&addressdetails=1", function(result) {
lat = result[0].lat;
lon = result[0].lon;
});
}
data = data + randomNumber() + ": " + lat + " " + lon + ",";
});
$(".data").val(data);
$(".form").submit();
});
The variable data
will contain the lat
and lon
for each div containing the class event
. The values will remain the same unless the address has been changed by the user, at which point they will be retrieved again via a JSON request.
The form should then be submitted.
How could I fix this? Thank you
Upvotes: 0
Views: 83
Reputation: 39
I think you should call $.getJSON
concurrently then deal all result while got all of them.
If $.getJSON
is not necessary for a location, you can create a immediate resolving deferred/promise to simulate a async call. So that we can deal with the same type of results (jQuery Promise Object).
Here is code (not test) and comments:
$(".button").click(function() {
// data = "";
// unnecessary
// $(".event").each(function() {
// use map to get promise objects for every ".event"
var promises = $(".event").map(function() {
original = $(this).find(".address").data("original");
location = $(this).find(".address").html();
// lat = $(this).find(".lat").html();
// lon = $(this).find(".lon").html();
// not need here
if (original !== location) {
return $.getJSON("http://nominatim.openstreetmap.org/search?q=" + location + "&format=json&polygon=1&addressdetails=1", function(result) {
lat = result[0].lat;
lon = result[0].lon;
});
} else {
// make value type same as json, it's a array of { lat, lon }
return $.Deferred().resolve([{
lat: $(this).find(".lat").html(),
lon: $(this).find(".lon").html()
}]).promise();
}
// data = data + randomNumber() + ": " + lat + " " + lon + ",";
// do it later, after all promise resolved.
});
$.when.apply(null, promises)
.done(function() {
// convert arguments to a array
var args = [].slice.apply(arguments);
data = args
.map(function(models) {
// convert each model to a string
var model = models[0];
return randomNumber() + ": " + model.lat + " " + lon;
})
// join each part with separator ','
.join(",");
// while got data, deal with it
$(".data").val(data);
$(".form").submit();
});
});
Upvotes: 1
Reputation: 781068
$.getJSON
is asynchronous, you can't refer to the result outside the callback function. And you don't want to submit the form until all the AJAX requests are done.
$.getJSON()
returns a Deferred
. You can make an array of all of them, and use $.when()
to wait for them.
$(".button").click(function() {
var promises = [];
var data = "";
$(".event").each(function() {
var original = $(this).find(".address").data("original");
var location = $(this).find(".address").html();
var lat = $(this).find(".lat").html();
var lon = $(this).find(".lon").html();
if (original !== location) {
promises.push($.getJSON("http://nominatim.openstreetmap.org/search?q=" + location + "&format=json&polygon=1&addressdetails=1", function(result) {
var lat = result[0].lat;
var lon = result[0].lon;
data += randomNumber() + ": " + lat + " " + lon + ",";
}));
} else {
data += randomNumber() + ": " + lat + " " + lon + ",";
}
});
$.when.apply($, promises).done(function() {
$(".data").val(data);
$(".form").submit();
});
});
Note that the order of the values in data
is unpredictable, since AJAX requests don't necessarily return in the same order they were sent.
You should also get in the habit of declaring your variables as local with var
(or let
in ES6).
Upvotes: 1