user3167249 user3167249 - 3 months ago 8
Javascript Question

HTML5 Geolocation Not Waiting for user Input

I am trying to create a web app that will prompt the user to allow the use of his location. I am using the following function.

function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position){
return("@" + position.coords.latitude + "," + position.coords.longitude);
}
);
} else {
return("Unknown");
}
}


My issue is that the function returns "undefined" before the user is even prompted to allow for location tracking. Does anyone know how I could modify this code to wait until after the user chooses? Also I can't seem to see what is throwing the undefined error.

Answer

Promises is a simple answer for this kind of issue. navigator.geolocation.getCurrentPosition is an asynchronous call - that means that you call the method and pass it a callback function, whenever the location is retrieved then your callback function will be called with the result value (location). Depending on the asynchronous function you're calling, it could take 1ms for your callback function to be called or 1 hour, all you know is that whenever the value is available, it will "notify" you.

In the case of your getLocation function, you either return nothing at all or you return the string Unknown. Notice that returning a result from the callback function(position){ has nothing to do with returning on getLocation. A very simple solution (without using Promises) is to simply give a callback to your getLocation function, so it would look like something like this:

function getLocation(callback) {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(
            function(position){
                callback("@" + position.coords.latitude + "," + position.coords.longitude)
            }
        );
    } else {
      return "Unknown";
    }
}

getLocation(function(res) { /* do something with the result */ });

As I mentioned before, another way of fixing this is to use Promises. Either use native ES6 promises or go for a widely used library like Bluebird (my favourite). With promises, the code would look something like this: (I recommend you to have a read about it since Javascript is all about asynchronous methods, so you should have a good grasp on these kind of issues)

function getLocation(callback) {
    var promise = new Promise(function(resolve, reject) {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(
                function(position){
                    resolve("@" + position.coords.latitude + "," + position.coords.longitude)
                }
            );
        } else {
          reject("Unknown");
        }
    });

    return promise;
}

var locationPromise = getLocation();
locationPromise
      .then(function(loc) { console.log(loc); })
      .catch(function(err) { console.log("No location"); });