I've been struggling with this for a few hours now, and even after reading several examples on Stack I've been unable to get this working. It doesn't help that I'm a JS newbie.
I'm trying to retrieve information about an address from the Google Geocoder API, and then pass the object over to another function. Per my reading I understand that function I'm using to retrieve the information is asynchronous, and therefore I need to use a callback function to read it. However, when I attempt to do this I still get 'undefined' returned by my console. I know that the information is coming from Google fine, since when I use console.log() on the result object it returns correctly.
Anyways, here's what I'm working with:
function onSuccess(position) {
getLocationData(position, function(locationData) {
console.log(locationData);
});
}
function getLocationData(position, callback) {
geocoder = new google.maps.Geocoder();
var location = 'Billings,MT';
if( geocoder ) {
geocoder.geocode({ 'address': location }, function (results, status) {
if( status == google.maps.GeocoderStatus.OK ) {
return results[0];
}
});
}
callback();
}
Like I mentioned though, all I get with this is 'undefined'. If I put 'console.log(results[0])' above the getLocationData() return, the object returned is correct though. Any help would be much appreciated.
Your problem is, that you didn't connect the callback to the return. As the geocode() function itself is already asynchronous, the return doesn't have any effect there. Instead you have to pass the values you are returning here directly to the callback-function. Like this:
function getLocationData(position, callback) {
geocoder = new google.maps.Geocoder();
var location = 'Billings,MT';
if( geocoder ) {
geocoder.geocode({ 'address': location }, function (results, status) {
if( status == google.maps.GeocoderStatus.OK ) {
callback(results[0]);
}
});
}
}
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Google map sync geocode delay
(2 answers)
Closed 4 years ago.
I am trying to get address info for my project. I can see the address by alert() method if i write it inside the geocode function. but if i outside of the function, it returns undefined.
tried to write the variable name like window.adres but didnt work. i think because of an another function with is parent of this.
how to make that variable global and change the value?
var geocoder = new google.maps.Geocoder;
var adres;
var latlng = {lat: parseFloat(lat), lng: parseFloat(lon)};
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
if (results[0]) {
adres = results[0].formatted_address;
//window.adres = ... is not working. i think because of an another function which is parent of these lines.
alert(adres); //returns address
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
alert(adres); //returns undefined
also i tried that
var geocoder = new google.maps.Geocoder;
var latlng = {lat: parseFloat(lat), lng: parseFloat(lon)};
var adres = geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
if (results[0]) {
return results[0].formatted_address;
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
alert(adres); //returns undefined too
If you set a global variable with window dot whatever, you will be able to get to it later by calling the same (fully qualified) variable.
Here is an example that proves this (run the snippet to see it in action).
function setVarInFunction(){
window.adres = 'here is some text';
}
console.log(window.adres); // should be undefined
setVarInFunction();
console.log(window.adres); // now there should be something
The reason alert(adres) is not working the way you expect is that:
you create a variable at the beginning
you execute an asynchronous request off to Google to do some work, and update your variable when it comes back from Google
you execute your alert to show the var value, but you have no guarantee that Google has actually responded yet with it's data (it almost certainly has not yet responded)
What do you want to do with that value? You almost certainly don't want to just alert() it, right? Whatever you want to do with it, you should do in the block where it comes back from Google with success or failure.
You are missing the ending of your anonymous function.
This is an issue related to the callbacks in javascript.
Geocoder takes time to process your request. Thus, you alert address while it is not yet defined.
I have updated your code to new coding standards and added comments :
let geocoder = new google.maps.Geocoder;
let latlng = { lat: parseFloat(lat), lng: parseFloat(lon) };
let address = null;
// 1. The geocoder starts the process to find the address
geocoder.geocode({'location': latlng}, (results, status) => {
// 3. The geocoder finally located the address, because it takes time.
if (status === 'OK') {
if (results[0]) {
// This updated the variable with the correct result.
address = results[0].formatted_address;
// You should call here a new function, in order to do the rest of your work
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
// 2. you output address
alert(address); // This won't work as address is set by the geocoder which is asynchronous
Hope this helps.
I am trying to find a set of latitude longitude values and assign it to a variable.
My code looks like this
var k = findLattitudeLongitude("Italy");
console.log(k) // comes undefined
function findLattitudeLongitude(input){
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': input}, function(results, status) {
var location = results[0].geometry.location;
return location;
});
}
but it comes as undefined. What is the best way to achieve the above requirement. Is there any other method?
Actually what you've done is correct.
The problem is the response received from Google geocoder is taking some time.
I've created a fiddle for a better understanding.
it's strange that the function return undefined, what you can do is to call another function, this way work with me fine, you can pass latitude and longitude params like the code below or the whole object
$( document ).ready(function() {
function getlatlan(){
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': "Italy"}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
dosome(results[0].geometry.location.nb,results[0].geometry.location.mb)
return true;
;
}});
}
function dosome(lat,lng){
console.log(lat,lng);
}
getlatlan();
});
This question already has answers here:
How do I return a variable from Google Maps JavaScript geocoder callback?
(5 answers)
Closed 9 years ago.
I just can't find what's wrong with this bit of code:
function getLocationName(latitude, longitude) {
if (isNaN(parseFloat(latitude)) || isNaN(parseFloat(longitude))) {
return false;
}
var locationName;
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(latitude, longitude)
// Reverse Geocoding using google maps api.
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
locationName = results[1].formatted_address;
alert(locationName);
}
else {
locationName = "Unknown";
}
}
else {
locationName = "Couldn't find location. Error code: " + status;
}
});
alert(locationName);
return locationName;
}
I call this from a jquery event handler like this:
$("#id").on("event", function (event, ui) {
$("#userLocation").text(getLocationName(latitude, longitude));
});
Weird part is that the first alert gets the correct value of 'locationName' but the second one always returns 'undefined'. I tried initializing the variable with a value and in that case the first alert again returned the correct location name but the second one returned the initialization value. This gives me a notion that this might be a variable scope related problem but I just can't figure what.
PS. I don't have any other variables (local/global) by the same name.
Update: The alert works fine now (thanks to Lwyrn's answer) but the return value is still wrong. I've followed the answers in the linked SO question and still I couldn't 'return' the right value. The alert did work fine.
You have to move "alert(locationName);" into the geocoder.geocode callback. Because geocoder.geocode executes an AJAX request. When you throw the alert the var locationName is still undefined (not set).
Try it like this
function getLocationName(latitude, longitude, callback) {
if (isNaN(parseFloat(latitude)) || isNaN(parseFloat(longitude))) {
return false;
}
var locationName;
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(latitude, longitude)
// Reverse Geocoding using google maps api.
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
locationName = results[1].formatted_address;
alert(locationName);
}
else {
locationName = "Unknown";
}
}
else {
locationName = "Couldn't find location. Error code: " + status;
}
alert(locationName);
callback(locationName);
});
}
To get the "return" you have to create a your own callback.
Try like this
$("#id").on("event", function (event, ui) {
getLocationName(latitude, longitude, function(result){
$("#userLocation").text(result);
});
});
As for the alert, the return is called before the ajax request. So you have to use a callback to be called when the ajax request has done his job!
Hi I am working with google maps API
I have this huge code, so I dont want to scare away people with code
Basically this is what I need to do
I have a javascript(1) function that I call from Html after someone clicks a button,
from that function I do some processing to calculate the latitudes and longitudes and call a custom function which uses the latitudes and longitudes and calls a google maps function. I need to pass that the value from the google maps call back function back to the javascript function (1)
here is how it goes
--------------File First.html----------------
<script type="text/javascript" src="functions.js"></script>
<script type="text/javascript">
function docalculation
{
.....some calculations for latlng......
var value = get_value(latlng);
}
</script>
<html>
.....html file....
<input type="button" value="Create Directions" onClick="docalculation()">
</html>
-------------------file functions.js----------------
var return_val;
function get_val(latlng)
{
geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': latlng}, function(results, status) {
return_val = (results[0].address_components[i].long_name);
alert(return_val); //here I get the value that I need in alert
}
alert (return_val); // here the value suddenly becomes undefined
return val; // hence returns undefined
}
Please help I am stuck here and could not find a solution even after 2 days of googling and trying everything I know.
any help appreciated thanks
The simplest solution that I am looking for would be some way to store the value of return_val into variable value
Thanks
That's because geocode() is asynchronous: it returns immediately but the callback function is invoked as soon as the response arrives. You need to accept a callback in get_val() and pass the value to this method instead of trying to return it (it's impossible):
function get_val(latlng, cb) {
geocoder = new google.maps.Geocoder();
geocoder.geocode({
'latLng': latlng
}, function (results, status) {
cb(results[0].address_components[i].long_name);
});
}
Usage:
get_value(latlng, function(longName) {
/* do something */
});
Here's how you could use ThiefMaster's answer to get multiple longitudes in one call. Not for the faint of heart.
/**
* #param {string[]} values longitude strings
* #param cb {function} The callback that will be passed a
* map keyed by latlng strings where each value
* is the long name of the street
*/
function getLongNames(values, cb) {
var returnValues = {};
var responseCount = 0;
var geocoder = new google.maps.Geocoder();
for (var i =0; i < values.length; i++) {
getSingleName(values[i], function(latLng, longName) {
returnValues[latLng] = longName;
responseCount++;
if (responseCount == values.length) {
cb(returnValues);
}
});
}
function getSingleName(latlng, cb) {
geocoder.geocode({
'latLng': latlng
}, function (results, status) {
cb(latlng, results[0].address_components[i].long_name);
});
}
}
And you call it like this
// The callback is the code that is run once all the latLng have been processed
getLongNames(["latLng1", "latLng2","latLng2"], function (valueMap) {
for (var latLng in valueMap) {
console.log("Latitude Longitude:" + latLng + " Long Name " + valueMap[latLng]);
}
});
I have a (hopefully quite simple) Javascript problem. I've search but found nothing that is really relevant to the problem.
Basically I have a function (addToGlobe) that calls two other functions (codeAddressLat and codeAddressLng) as it runs. The two called functions should both return a float value to the first function, which then uses them. The subfunctions definitely work correctly - I did a print statement to check that the "numfinal" variable in each has a value, and it does.
However, when I add print statements to the calling function (as commented in the code), it returns 'undefined'. Therefore, the problem seems to be when the numfinal value is returned.
Thanks :)
function addToGlobe(uname, uid, pmcity) {
// Get lat & long of city
var pmlat = codeAddressLat(pmcity);
var pmlong = codeAddressLng(pmcity);
log(pmlat); // PROBLEM! Prints 'undefined'
log(pmlong); // PROBLEM! Prints 'undefined'
// Rest of function removed to keep it simple
}
function codeAddressLat(inputcity) {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
geocoder.geocode( { 'address': inputcity}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var llsplit = new Array();
bkresult = String(results[0].geometry.location);
bkresult = bkresult.replace(/[\(\)]/g, "");
llsplit = bkresult.split(',');
numfinal = parseFloat(llsplit[0]);
return numfinal;
} else {
log('<b><font color="#C40031">Geocode was not successful:</b> ' + status);
}
});
}
function codeAddressLng(inputcity) {
// Basically the same function as above. Removed for simplicity
}
codeAddressLat is not actually returning anything. The anonymous function it passes to geocoder.geocode is.
Since geocoder.geocode is running asynchronously, codeAddressLat can't wait around for its answer. So codeAddressLat really can't return anything of value. Instead codeAddressLat needs to become asynchronous too. This is a common pattern in JavaScript.
function addToGlobe(uname, uid, pmcity) {
codeAddressLat(pmcity, function(pmlat) {
// do something with pmlat
});
...
}
function codeAddressLat(inputcity, callback) {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
geocoder.geocode( { 'address': inputcity}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var llsplit = new Array();
bkresult = String(results[0].geometry.location);
bkresult = bkresult.replace(/[\(\)]/g, "");
llsplit = bkresult.split(',');
numfinal = parseFloat(llsplit[0]);
// instead of returning, call the callback with the result
callback(numfinal);
} else {
log('<b><font color="#C40031">Geocode was not successful:</b> ' + status);
}
});
}
You don't have a return statement in codeAddressLat, you have one inside a callback function defined inside codeAddressLat.
Your function codeAddressLat is not actually returning a value but calling function that you pass a callback function which is returning a value. You need to wait until the geocode operation is complete to retrieve the value of numfinal.
Your function codeAddressLat is not returning any value at all hence you are getting undefined as output.
The geocode request in the codeAddressLat method call and will not return the value to the caller. Your return is of a different scope.
Does this work?
function codeAddressLat(inputcity) {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
return geocoder.geocode( { 'address': inputcity}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var llsplit = new Array();
bkresult = String(results[0].geometry.location);
bkresult = bkresult.replace(/[\(\)]/g, "");
llsplit = bkresult.split(',');
numfinal = parseFloat(llsplit[0]);
return numfinal;
} else {
log('<b><font color="#C40031">Geocode was not successful:</b> ' + status);
}
});
}
That geocoder.geocode function looks like it is asynchronous. Your codeAddressLat and codeAddressLng functions returns void before the geocoder.geocode function has got data back from the server.
A way to get around it is to nest your calls to geocoder.geocode and use variable scoping so that when all the AJAX calls have returned you can call your addToGlobe function passing the two parameters you want.
Something like this:
codeAddressLatAndLong(pmcity);
function addToGlobe(pmlatlat, pmlatlong) {
log(pmlat); // PROBLEM! Prints 'undefined'
log(pmlong); // PROBLEM! Prints 'undefined'
// Rest of function removed to keep it simple
}
function codeAddressLatAndLong(inputcity) {
// stuff
geocoder.geocode( { 'address': inputcity}, function(results, status) {
// stuff goes here
pmlat = parseFloat(llsplit[0]);
geocoder.geocode({...}, function(results, status) {
// more stuff
pmlatlong = something;
addToGlobe(pmlatlat, pmlatlong);
});
});
}
Welcome to the world of AJAX.