Navigator.geolocation is really slow!

Hello all!

I’m having a minor problem with the navigator.geolocation if statement. In my code, the function always runs through and I don’t experience errors, however it takes about 5-10 seconds every time I refresh the page to grab my longitude and latitude again. Is there a fix to this? Will I just have to live with it?

Is this the same with all browsers? It could also just be the area you live in. Browser geolocation uses a combination of different parameters to suss out your location, and if you live far away from other wifi connections, it could take much longer to get the data the browser needs. You might also check to see that the browser’s location accuracy setting is set to its highest, if that option is available to you. While unlikely, I guess there’s a possibility you’ve written some code that makes the geolocation seem like it’s taking longer than it actually is.

You enable caching of the position data, but I don’t know if that persists through refreshes.

var options = {
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0
};

// ...

navigator.geolocation.getCurrentPosition(success, error, options);

Even when I use the exact code from the example in https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition I get a timeout after the specified 5 secs (using a button with onclick=“getCurrentPosition()”).

If I don’t have a timeout property, it takes 10-20 seconds before returning the position.

I’m in a dense area of the Bay Area with fast internet.

I’ve tried this on chrome, firefox, and safari.

navigator.geolocation works but it’s slow.

Even for the simple Get Geolocation Challenge, when I “run tests” it returns the coordinates after 2 seconds, and if I reload the page and “run tests” again, it takes 33 seconds to show the coordinates!

Has anyone found a way to make navigator.geolocation faster when the the function has already been cached? Anyone else encounter this problem?

You could try caching the previous location in the user’s browser using localStorage so you have something to display sooner:

const oldCoords = localStorage.getItem('coords');

if (oldCoords) {
  showWeather(JSON.parse(oldCoords));
}

navigator.geolocation.getCurrentPosition(pos => {
  const newCoords = JSON.stringify(pos.coords);
  localStorage.setItem('coords', newCoords);
  showWeather(newCoords);
}, handleError);
1 Like

@lionel-rowe
That sounds like a great solution.

However, what happens if the user flies from Hawaii to Alaska, without closing their browser and clearing cache in between? With this localStorage approach, they wouldn’t get the appropriate update to their weather report and location.

navigator.geolocation does work fast the first time the code runs and slow each time after. All I need to do to get that “first-time” speed, is to restart the browser. But I can’t tell the user to do that :rofl:

Is there any code that has the same effect on navigator.geolocation as a browser restart? :sweat_smile::stuck_out_tongue_closed_eyes:

ps. sorry if i misunderstood localStorage…very new concept for me :innocent:

Yes, navigator is working very strange lately. I’ve noticed it in codepen so I sent them a note.

You are right that local storage would not work if someone moved somewhere else - it stores stuff in the browser memory.

Another option (besides navigator) is to use an api like ip-api.com - it will figure out your ip and return information, including approximate location (close enough for weather). It would just mean one more AJAX call to get a JSON.

1 Like

Well, based on the code I posted, they’d see the weather in Hawaii and then the weather in Alaska.

Technically, the code I posted is somewhat flawed, because it contains a race condition (assuming showWeather involves asynchronously calling a weather API). If somehow the second weather API call returned before the first, the user would see the weather in Alaska first and then the weather in Hawaii. I’ll leave fixing that as an exercise for someone else.

Another improvement would be caching the previous weather, plus a timestamp, as well as the previous location. Not only would this remove the race condition, but additionally you could show the user something immediately on page load. It’d look something like this:

Weather for Hawaii

Last updated Tue Apr 10 2018 10:15:05 UTC-10 (Pacific/Honolulu)
Sunny, 30°C

Then after a few seconds (async getCurrentPosition + async weather API call), it would change to something like this:

Weather for Alaska

Last updated Wed Apr 11 2018 10:15:05 UTC-9 (America/Anchorage)
Cloudy, 5°C

1 Like

Wow! @lionel-rowe great solution! :clap:

I just noticed that even FCC’s model codepen for this challenge has this issue of loading fast the first time, and slow the other times, unless the browser is refreshed. Your code would definitely be an improvement!

I was tempted to think it’s a corner case. But people usually check the weather once a day, and many people don’t close their browsers every day, so I think your code is a helpful addition!

@kevinSmith That’s good to know you’ve been noticing this too. And interesting to know that it could be codepen’s fault. Thank you!

… I’m curious if lionel-rowe’s response changes your mind about this?

Yes, I didn’t look closely enough at Lionel’s code. He’s right, if it has a location it will load that and then ask for new ones.

He’s right, that should work. Besides the problems he mentions is that sometimes I can’t even get an initial response from navigator. I think there is a big problem with navigator (on codepen I assume) and we don’t know when (or if) it will be fixed. I would suggest using an outside api. Even with that, Lionel’s idea is a good one, improving UX.

I don’t have any problem with geolocation or the weather api. Here is my codepen made 2 yrs ago thats still functional. weather app

At least if there is a small delay in getting the coordinates and weather response you may mask them by some fade in animation or something like that

No matter what free weather api you are going to use, in order to avoid unnecessary calls to the api, I highly recommend in codepen settings->behavior to disable the auto-updating preview that will force codepen to rerun the code each time you make a little change(it can be just a letter changed and voila you have another call to the api).

To also avoid unnecessary calls to the weather api i would just make one call to the api, grab the response, save it in a json var and work with that var until you finish all design and js code then you can switch back to live api calls.

I ran your code. It did stall a bit on a few navigator calls, as much as 10 seconds. But it did eventually return - something I’ve seen it not do. You quota on the weather API is exceeded though (or there is a key problem.)

+1 on disabling auto-updating and on manually caching the AJAX responses in dev.

is it reporting the right location and weather for you?

Location yes. API was getting an error before but is working now.

For further investigation, I wrote a pen to test calls to navigator. It makes a call and tells how long it took, then makes another call.

I was getting delays as much as 20 seconds. It was oddly consistent in being just short of 20 seconds, especially once it got going. When I exported it and ran it locally, I got the same result. That was with chrome so I thought I’d try it with firefox. I got delays again, but now around 4 seconds max.

Hmmm.

I’m guessing that the browsers have some kind of internal throttling an multiple calls to navigator. The first few calls are often fast, but later once seem to hover just shy of that browser defined upper limit.

1 Like

Hi,

In Javascript there is already available a method for “watching” the position without the need to make several calls to navigator.geolocation.getCurrentPosition. The method is called watchPosition, and I made this pen for you to have a look if you’re interested. Careful, because the timeout is set to 5 seconds, so it refreshes its position every 5 seconds.

Hope it’s helpful.

Happy coding!

Thank you! :smiley:The first time I ran it, I got “`Error! Unavailable position.” probably because the browser had just made a navigator.geolocation when I ran kevinSmith’s call

After quitting Chrome and loading your watchPosition page again, it worked. Thanks for pointing out that method!

that theory sounds plausible based on my experiences :clap:

1 Like

It works way better on the phone. You can see the coordinates changing very quickly. :slight_smile:

Yes, watchPosition is useful, but I think you missed the point. The point wasn’t to find the best way to have an app regularly update positions. The point was to show how getCurrentPosition starts out fast and then slows to a slow (seemingly browser throttled) speed on subsequent calls - something that happens in development a lot.

Also, your pen doesn’t work for me - it keeps timing out.

PS - What part of Spain are you in? My wife and I are hoping to move to Barcelona in the next few years.

2 Likes

Yes, navigator.geolocation has been working incredibly quickly for me on the phone too, with all the tests I’ve done on various code’s using the navigator.geolocation method.

Just wanted to add a note to say that the above line doesn’t work. Possibly because pos.coords is a complex object that can’t be stringified… it just returns an empty {}

I had to change it to

            const newCoordinates = JSON.stringify({
              lat: position.coords.latitude,
              lng: position.coords.longitude
            });
            // console.log('stringified coordinates', newCoordinates);
            localStorage.setItem('coords', newCoordinates);

And then I was able to save them to localStorage