0

I am trying to use the Javascript Geolocation API to get the user's longitude and latitude. I would like to be able to get that information by calling the getCoords() function but am having a problem. This code:

function getCoords() {

    var coords = 5;
    var deferred = $.Deferred();

    getPosition = function() {
        navigator.geolocation.getCurrentPosition(
            function(position){
                deferred.resolve({
                    longitude: position.coords.longitude,
                    latitude: position.coords.latitude,
                });
            }, function(error) {
                deferred.reject();
            });
        return deferred.promise();
    }

    $.when(getPosition())
        .done( function(data) { 
            coords = data;
            console.log(coords); // Statement A
        });
    console.log(coords) //Statement B 
    return coords;
}

console.log(getCoords().toString()); //Statement C  

Outputs the following to the console

5  //Statement B
5  //Statement C
Object {longitude: 41.40338, latitude: 2.17403}  //Statement A

Which makes sense because the geolocation API is asynchronous. If I change the second half of the code to:

$.when(getPosition())
    .done( function(data) { 
        coords = data;
        return coords;
    });
}

I get the following error message:

Uncaught TypeError: Cannot call method 'toString' of undefined
    (anonymous function)

All of the other examples I have found on the web have the $.when part of the code output to an alert instead of a return method. Anyone have any thoughts on how to make getCoords() return the correct object? Thanks!

duner
  • 1
  • And where are you returning it, not that it matters as you can't return a value from an async operation that way. The function you are returning it to will likely already have completed whatever it is it does ? – adeneo Aug 14 '13 at 18:44
  • 1
    yeah, that logic isn't going to work. you cant do `var coords = getCords()` if `getCords` is making an ajax request. – Kevin B Aug 14 '13 at 18:45

1 Answers1

2

You'll still have the same issue you were trying to resolve by using a deferred. You just wrapped the function that returns a deferred in another function that tries to return the async result synchronously. getCoords has to return a deferred, and the caller has to know about and handle the promise object.

I would write it like this:

function getCoords() {

    var coords = 5;
    var deferred = $.Deferred();

    navigator.geolocation.getCurrentPosition(function (position) {
        deferred.resolve({
            longitude: position.coords.longitude,
            latitude: position.coords.latitude,
        });
    }, function (error) {
        deferred.reject();
    });

    return deferred.promise();
}

//elsewhere
getCoords().done(function (data) {
    console.log(data);
}).fail(function () {
    console.log('failed');
});
Jason P
  • 26,984
  • 3
  • 31
  • 45