1

I'm trying to return a City from lat/long using a callback from AJAX, but the return is undefined although the AJAX is calling the callback with correct value (city).

I've been reading How do I return the response from an asynchronous call? but i am tryng to figure out why the City is still being returned and written as undefined.

Here's the whole code:

function getLocation(id) {
    x = document.getElementById(id);
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function showPosition(position) {
            x.innerText = GetCity(position.coords.latitude, position.coords.longitude, returnCity);
        });
    } else {
        this.innerHTML = "Geolocation is not supported by this browser.";
    }
}

function returnCity(result) {
    return result;
}

function GetCity(lat, long, callback) {
    $.ajax({
        type: "GET",
        dataType: "json",
        url: "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + lat + "," + long + "&sensor=false",
        data: {},
        success: function (data) {
            var city;
            $.each(data['results'], function (i, val) {
                $.each(val['address_components'], function (i, val) {
                    if (val['types'] == "locality,political") {
                        if (val['long_name'] != "") {
                            city = val['long_name'];
                        } else {
                            city = "N/A";
                        }
                    }
                });
            });
            callback(city);
        },
        error: function () {
            alert('error');
        }
    });
}
Community
  • 1
  • 1
Dillinger
  • 341
  • 3
  • 16

1 Answers1

0

GetCity doesn't return a value, that's why it's always coming back as undefined. Asynchronous programming takes time to get the trick of, but in general you usually don't usually use the returns from functions, you're usually passing around callbacks. The tricky bit for what you're trying to do is that you need to keep your element in proper scope so that you can set the inner text in the callback. The code below gives you an example using an anonymous function instead of a named function callback.

function getLocation(id) {
    x = document.getElementById(id);
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function showPosition(position) {
            GetCity(position.coords.latitude, position.coords.longitude, function(result) {
                x.innerText = result;
            });
        });
    } else {
        this.innerHTML = "Geolocation not supported by browser.";
    }
}

function GetCity(lat, long, callback) {
    $.ajax({
        type: "GET",
        dataType: "json",
        url: "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + lat + "," + long + "&sensor=false",
        data: {},
        success: function (data) {
            var city;
            $.each(data['results'], function (i, val) {
                $.each(val['address_components'], function (i, val) {
                    if (val['types'] == "locality,political") {
                        if (val['long_name'] != "") {
                            city = val['long_name'];
                        }
                        else {
                            city = "N/A";
                        }
                    }
                });
            });
            callback(city);
        },
        error: function () { alert('error'); }
    });
}
Dillinger
  • 341
  • 3
  • 16
Samuel
  • 16,923
  • 6
  • 62
  • 75