I am fairly new to Javascript so forgive me if this has been answered but I cannot get this to work nor can I find the answer anywhere online. I am trying to return an address using Google's Maps JavaScript API. I can print it to the console inside the inner function but if I try to access it outside of that function, it is printing undefined. How can I access the variable in the outer function and return it??
function getAddress(latlng) {
var address;
var service = new google.maps.Geocoder();
service.geocode({ location: latlng}, function(results, status) {
if (status === "OK") {
if (results[0]) {
address = results[0].formatted_address;
console.log(address); //prints address
}
}
});
console.log(address); //prints undefined
}
The issue is a classic asynchronous gotcha, where address
is available only once the callback is invoked, where usually, when a callback is needed, it means there are no guarantees its result will be available outside its execution, and since I believe there is a network request involved, there's no way the result can arrive in time for you to log address
right after.
var value;
api.thing(callbackThatSetsValue)
console.log(value);
The gits of the problem is there: value
can't point at anything, as the callbackThatSetsValue
will be invoked after the next line of code gets executed.
There are at least 2 options here, let's see how these look like ...
Wait for the result
This options allows you to do anything you need once the address is resolved.
function getAddress(latlng, after) {
var service = new google.maps.Geocoder();
service.geocode({ location: latlng}, function(results, status) {
if (status === "OK")
if (results[0])
after(results[0].formatted_address);
});
}
Above utility allows you to getAddress({lat:50,lng:1}, console.log)
, as example, or pass any callback that should render, use, display, such address.
The pitfall in this approach is that if status
is not OK
, you have a hanging callback forever, as it won't ever get invoked.
Alternatively, you can put an else
in that function and pass an error, or null
, and react accordingly in the callback.
The Promise way
Is the most common pattern these days, hence my suggestion.
function getAddress(latlng) {
return new Promise(function ($, _) {
var service = new google.maps.Geocoder();
service.geocode({ location: latlng}, function(results, status) {
if (status === "OK")
if (results[0])
$(results[0].formatted_address);
_(new Error("status was " + status));
});
});
}
In this case you getAddress({lat:50,lng:1}).then(console.log).catch(console.error)
, so you have an escape/way to react when address is not valid.