navigator.geolocation.getCurrentPosition sometimes works sometimes doesn't

Viewed 322992

So I have a pretty simple bit of JS using the navigator.geolocation.getCurrentPosition jammy.

$(document).ready(function(){
  $("#business-locate, #people-locate").click(function() {
    navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
  });

  navigator.geolocation.getCurrentPosition(foundLocation, noLocation);

  function foundLocation(position) {
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
    var userLocation = lat + ', ' + lon;
    $("#business-current-location, #people-current-location").remove();
    $("#Near-Me")
      .watermark("Current Location")
      .after("<input type='hidden' name='business-current-location' id='business-current-location' value='"+userLocation+"' />");
    $("#people-Near-Me")
      .watermark("Current Location")
      .after("<input type='hidden' name='people-current-location' id='people-current-location' value='"+userLocation+"' />");
  }
  function noLocation() {
    $("#Near-Me").watermark("Could not find location");
    $("#people-Near-Me").watermark("Could not find location");
  }
})//end DocReady

Basically what's happening here is we get the current position, if it's obtained, two "watermarks" are placed in two fields that say "Current Position" and two hidden fields are created with the lat-long data as their value (they're removed in the beginning so they don't get duplicated every time). There are also two buttons that have a click function tied to them that do the same thing. Unfortunately, every third time or so, it works. What's the problem here???

25 Answers

You don't get an error message because it has no timeout by default (At least i think). I have had the same problem with firefox only for me firefox always gives an timeout. You can set a timeout yourself like this.

My function works great in chrome but i get a timeout everytime in firefox.

    navigator.geolocation.getCurrentPosition(
        function(position) {
            //do succes handling
        },
        function errorCallback(error) {
            //do error handling
        },
        {
            timeout:5000
        }
    );

I recommend to watch your errors carefully. Be expected for everything. Have a backup plan for everything. I use some default values or values from my database myself in case both google geolocations and navigator geolocations fails.

As of mid 2020, none of the answers here provides any explanation, just hacking or guessing.

As @Coderer points out before me, secure context (https) is required today, so on more and more devices geolocation doesn't work at all with plain http:

Secure context This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

The third parameter of getCurrentPosition() (and watchPosition() which is more suitable here) is PositionOptions object consisting of these properties:

  • enableHighAccurancy (default false): if set to true, response is slower and more accurate. If you got timeout errors, keep this to false. If the accurancy is low, set it to true. In my tests 1s delay with 1-2 meters precision and there was no difference between true and false on UMAX tablet. I tested also on older iPhone with 5 meters oscilation if set to false. You can also measure accurancy in GeolocationCoordinates.accurancy property and decide dynamically.
  • timeout (default infinity): milliseconds before the API gives up and calls the error handler (the second parameter). Today, 5s (5000) is reasonable and in some cases 10s can make sense. Useful if you want to have plan B when geolocation sensor data is not available.
  • maximumAge (default 0): milliseconds when cached value is valid, the device may decide to use valid cached data instead of sensor measure. Set this to Infinity on static locations, keep at 0 otherwise.

As @YoLoCo points out before me, getCurrentPosition() and watchPosition() interferes and I confirm his results in 2020. Generally, use watchPosition instead of getCurrentPosition periodical calls.

The second parameter passed to Geolocation.getCurrentPosition() is the function you want to handle any geolocation errors. The error handler function itself receives a PositionError object with details about why the geolocation attempt failed. I recommend outputting the error to the console if you have any issues:

var positionOptions = { timeout: 10000 };
navigator.geolocation.getCurrentPosition(updateLocation, errorHandler, positionOptions);
function updateLocation(position) {
  // The geolocation succeeded, and the position is available
}
function errorHandler(positionError) {
  if (window.console) {
    console.log(positionError);
  }
}

Doing this in my code revealed the message "Network location provider at 'https://www.googleapis.com/' : Returned error code 400". Turns out Google Chrome uses the Google APIs to get a location on devices that don't have GPS built in (for example, most desktop computers). Google returns an approximate latitude/longitude based on the user's IP address. However, in developer builds of Chrome (such as Chromium on Ubuntu) there is no API access key included in the browser build. This causes the API request to fail silently. See Chromium Issue 179686: Geolocation giving 403 error for details.

In our case it always works the first time but rerunning the function more than 3-4 times, it fails.

Simple workaround: Store it's value in LocalStorage.

Before:

navigator.geolocation.getCurrentPosition((position) => {
  let val = results[0].address_components[2].long_name;
  doSthWithVal(val);      
}, (error) => { });

After:

if(localStorage.getItem('getCurrentPosition') !== null) {
  doSthWithVal(localStorage.getItem('getCurrentPosition'));
}
else {
  navigator.geolocation.getCurrentPosition((position) => {
      let val = results[0].address_components[2].long_name;
      localStorage.setItem('getCurrentPosition',val);
      doSthWithVal(val);      
  }, (error) => { });
}

This happened to me when using Firefox's responsive design mode. There has been a bug report filed. For now, just don't use responsive design mode while using the Geolocation API.

May be it helps some one, On Android i had same issue but i figured it out by using setTimeout inside document.ready so it worked for me secondly you have to increase the timeout just incase if user allow his location after few seconds, so i kept it to 60000 mili seconds (1 minute) allowing my success function to call if user click on allow button within 1 minute.

Related