Asynchronous Google Maps request throwing off Javascript - javascript

I'm working on someone else's code, and I am trying to use Google maps API to convert a street address into latitude and longitude coordinates:
var start_lng;
var end_lat;
var end_lng;
getLat(start);
getLng(start);
function getLat(loc) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': loc}, function postcodesearch(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var lat = results[0].geometry.location.lat();
alert(lat);
return lat;
//alert(start_lng);
}
else {
alert("Error");
}
});
}
function getLng(loc) {
var geocoder_lng = new google.maps.Geocoder();
geocoder_lng.geocode({'address': loc}, function postcodesearch(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var lng = results[0].geometry.location.lng();
alert(lng);
return lng;
}
else {
alert("Error");
}
});
}
So far, so good. In the code below, I take that latitude and longitude and perform various calculations with them:
alert("DO REST");
var start_p = new google.maps.LatLng(start_lat, start_lng);
alert(start_p);
var end_p = new google.maps.LatLng(end_lat, end_lng);
The problem is that since the call that gets the latitude and longitude is asynchronous, the code below doesn't wait to get the values before it tries to use them. They show up as undefined. I tried putting the second half of the code in its own function and calling that at the end of the longitude request, but that only worked if the longitude call happened to finish first. I also tried $.ajax({ async:false}) but that didn't do anything. This is my first time dealing with AJAX, so I'm really not sure which way to go.

For the "handler" code, use a callback instead:
function getLatLng(loc, callback) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': loc}, function postcodesearch(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
callback(lat, lng);
}
}
}
getLatLng(function(lat, lng) {
alert("DO REST");
var start_p = new google.maps.LatLng(lat, lng);
});
If you need to make two calls to the geocoder, then you can always nest those calls, and put the callback after both are complete. Something like:
function getLatLng(locStart, locEnd, callback) {
geocoder.geocode({ }, function(results1) {
geocoder.geocode({ }, function(results2) {
callback(results1.lat, results1.lng, results2.lat, results2.lng);
});
});
}
getLatLng(loc1, loc2, function(lat1, lng1, lat2, lng2) {
});

use global flag variables
for example:
var flag_lat = var flag_lnt = 0;
then add in your postcodesearch functions flag_lat=1; and flag_lng=1; respectively
and in the end of each postcodesearch function check
if (flag_lat && flag_lng)
{
do_the_things_function();
flag_lat = flag_lng = 0; //reset the flags
}

Related

Ember: Having trouble trying to use this.set to set a field with a variable declared inside an if statement

this is probably very easy for most you, but I really can't figure out what could be wrong with my code and I feel like I tried everything possible. Basically what I want to do, is to geocode a string adress, and store the result in my database.
I managed to get the geocode part to work, as it sends back the latitude and longitude. Now, I would like to store the result back in my database.
Usually I use this.set('myfield', myvar) but myvar is set inside an "if" and it looks like it prevent me to do that.
What can I do ?
Here is my code inside the "actions" section of my controller:
geocode(location, mylat, mylng) {
const google = window.google;
var geocoder = new google.maps.Geocoder();
var latlng = "";
var lat = "";
var lng = "";
geocoder.geocode( { 'address': location }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
latlng = results[0].geometry.location;
lat = latlng.lat();
lng = latlng.lng();
alert(lat); // it works
alert(lng); // it works too
this.set(`model.lat`, latlng); //not working here
}
}
);
alert(latlng); // not working
this.set(`model.lat`, latlng); //not working too
},
I spent maybe 8 hours trying to solve this and I'm totally lost, so any help would be sincerely greatly appreciated.
Many thanks in advance,
In the callback of geocode method, the this is not defined.
Here geocoder.geocode( { 'address': location }, function(results, status)
You can keep a ref to this like this :
actions: {
geocode(location, mylat, mylng){
const google = window.google;
var geocoder = new google.maps.Geocoder();
var latlng = "";
var lat = "";
var lng = "";
const self = this;
geocoder.geocode({'address': location}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
latlng = results[0].geometry.location;
lat = latlng.lat();
lng = latlng.lng();
alert(lat); // it works
alert(lng); // it works too
self.set(`model.lat`, latlng); //not working here
}
});
alert(latlng); // not working
this.set(`model.lat`, latlng); //not working too
}

Google map Geocoder [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 6 years ago.
I Using the google geocoder to get the lat and lng, when initMap had been called, I got two alert, first value is undefined ,and second get the lat value, what is the problem to get the undefined value, and how to resolve this? I need to get the value immediately.
function initMap(){
var addr = '1600 Amphitheatre Parkway, Mountain View, CA';
var code = getLatLng(addr);
alert(code.lat); // --> alert_1
}
function getLatLng(addr) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': addr }, function (results, status) {
var lat,lng = 0;
if (status == google.maps.GeocoderStatus.OK) {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
}
alert(lat); // --> alert_2
return {lat : lat,lng : lng};
});
}
The function geocode is an asynchronous function. Therefore, you get undefined for code.lat in the alert of the initMap function and the geocoded value in the getLatLng function. You can add a callback function to the parameters of the getLatLng function to solve your problem like this:
function initMap() {
var addr = '1600 Amphitheatre Parkway, Mountain View, CA';
getLatLng(addr, function(code) {
alert(code.lat);
});
}
function getLatLng(addr, cb) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': addr }, function (results, status) {
var lat,lng = 0;
if (status == google.maps.GeocoderStatus.OK) {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
}
cb({lat: lat, lng: lng});
});
}

aJax request, wait for it to complete

im using the Google API, i want to make it that there can be multiple addresses marked on the map so im using the Geocoder. However the rest of my code is running before this Geocoder returns the result it seems!
// Handle addresses
var addressesHandled = [];
function handleAddresses(addressObj) {
for (i = 0; i < addressObj.length; i++) {
addressesHandled[i] = new Address(addressObj[i]['title'], addressObj[i]['address'], addressObj[i]['latlng'], addressObj[i]['defaultOpen']);
}
}
// Address object
function Address(title, address, latlng, defaultOpen) {
this.title = title;
this.address = address;
this.latlng = latlng;
if (latlng == undefined) {
this.latlng = codeAddress(address);
}
this.defaultOpen = defaultOpen;
}
As you can see im going through each object and getting the address if the lat and lng values are undefined. If these are undefined I then execute the codeAddress function which will get the lat and lng values from the current address, however I think that the rest of the script is still running whilst this happens!
Below is the codeAddress function, I thought I was unable to the return the result however now I believe that it simply isn't being returns quick enough.
How can I fix this issue so the rest of my script waits until each address has had it's lat and lng calculated!?
function codeAddress(address, callback) {
var geocoder;
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var loc = [];
// loc = { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng() };
loc[0] = results[0].geometry.location.lat(); loc[1] = results[0].geometry.location.lng();
console.log(loc);
callback(loc);
} else {
console.log("Geocode was not successful for the following reason: " + status);
}
});
}
Edit:
Hmm, I just thought would it be easier just to process the marker and add it to the map as each geocode function has it's result returned ?

Reverse geocoder not working properly when used in a loop

My problem is with reverse geocoding using Google Maps. I would like to geocode n number(less than 15) of latitude and longitude coordinates so that I can plot a route using the addresses obtained. My problem is when I am using it in a loop it is not giving addresses in the order of lat-lng coordinates passed. The loop is not executing properly. The part of the code that I am having trouble with is:
for(var i=0;i<tlength;i++){
alert(i);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': latlng[i]},function(results, status) {
alert(i);
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
var add=results[0].formatted_address;
address.push(add);
}
}
});
}
The address array obtained is not in order with the latlng array. Second latlng is getting geocoded first and also the value of i from the 2nd alert box is always 6(in this case tlength=6). It should change from 0 to 5. But it's not happening. Can someone help me with this. Or is their any other way to plot routes using latlong coorinates directly?
Geocoding is asynchronous. The ordering of the callbacks is not guaranteed in in time. One fix would be to use function closure to associate the input index to the callback. Note that the geocoder is subject to a quota and a rate limit. If you don't check for the status returned you won't know when you run into the limit. (the alerts in the code below will get really annoying if you have lots of points in your array...)
var geocoder = new google.maps.Geocoder();
function reverseGeocode(index) {
geocoder.geocode({'latLng': latlng[index]},function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
var add=results[0].formatted_address;
address[index] = add;
} else alert("no results for "+laglng[index]);
} else alert("Geocode failed: "+status);
});
}
for(var i=0;i<tlength;i++){
reversGeocode(i);
}
You need to use like this error in your code :
var latlng = new google.maps.LatLng(51.9000,8.4731);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': latlng},function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
var add=results[0].formatted_address;
//address.push(add);
alert(results[0].formatted_address);
}
}
});
And for your code you need to pass like this:
for(var i=0;i<tlength;i++){
var latlng = new google.maps.LatLng(latlng[i]);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': latlng},function(results, status) {
alert(i);
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
// var add=results[0].formatted_address;
address.push(results[0].formatted_address);
}
}
});
}

Return Multiple Values From javascript function giving Error in Google Maps V3

What I want to do is that I need to create markers from stored location of user. So for that I need latitude and longitude. I got the lat & lon in my function get_current_user_lat_lon . Now I want to return both lat & lon through Object but my return is not working....
function initialize(){
var var_get_current_user_lat_lon = get_current_user_lat_lon();
var latitutde = var_get_current_user_lat_lon.latitutde;
alert(latitutde);// not even alert
var longitutde = var_get_current_user_lat_lon.longitutde;
alert(longitutde); // not even alert
}
function get_current_user_lat_lon(){
var address = $("#hidden_current_location").val();//Working fine
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var variable = results[0].geometry.location;
var lat = variable.lat();
var lon = variable.lng();
alert(lat); //Working fine
alert(lon); //Working fine
//return not working here
}
//return not working here
});
return {latitutde: lat , longitutde : lon};// giving error lat.lon is not defined means return not working here
}
Your "lat" and "lon" variables are declared inside the callback from "geocode()". Even if you declared them outside it, however, the overall idea would not work. The "geocode()" function is asynchronous; that's the reason there's a callback function in the first place.
Instead of structuring your code so that your "get_current_user_lat_lon()" function returns a value, follow the lead of the Google architecture and make your own function take a callback:
function get_current_user_lat_lon( callback ){
var address = $("#hidden_current_location").val();//Working fine
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var variable = results[0].geometry.location;
var lat = variable.lat();
var lon = variable.lng();
callback({latitude: lat, longitude: lon});
}
});
}

Categories