I have a web app that asks the user for their GPS location. It works fine using pretty standard code that looks something like this:
function getpos_callback( a ) {
top.location.href = 'location.php?lat=' + a.coords.latitude + '&lon=' + a.coords.longitude;
}
function error_callback( er ) {
top.location.href = 'location.php?err=1';
}
if ( 'geolocation' in navigator ) {
navigator.geolocation.getCurrentPosition( getpos_callback, error_callback, {
enableHighAccuracy: true,
maximumAge: 300000, // 300 seconds = 5 min = max age of cached value to use
timeout: 8000, // 8 seconds
} );
}
Here's the problem: on a desktop browser, it can take quite some time (4-6 seconds, and as long as 8, per the code) to determine the location. Even with mobile sometimes it can be sluggish. These seconds feel like an eternity when the user just wants to get on with using the site.
What I'd like to do is let the user in right away, but somehow "spawn a task" to ask the browser for the location in the background, and then have it pass that location to me in the background when the location is retrieved.
Is this possible?
The method navigator.geolocation.getCurrentPosition
is asynchronous by definition. It's specified by W3C to return immediately. You can check the specification for details.
So, you can simply call the function that "let the user in" right after calling getCurrentPosition
before having the success callback being called. The method getCurrentPosition
will have already "spawn a task" in the background when you do that.
The problem in your code is that you're changing the URL of the webpage after receiving the callback, inside the getpos_callback
function. I suggest you to change this behavior by updating the UI state using JS instead of reloading the page with the lat/lng parameters.
Refactoring your code, it would look like:
function getpos_callback( a ) {
// Comment the line bellow to avoid loading the page
// top.location.href = 'location.php?lat=' + a.coords.latitude + '&lon=' + a.coords.longitude;
updateScreen(a.coords.latitude, a.coords.longitude);
}
function updateScreen(lat, lon) {
// Update the UI with the lat/lon received instead of getting it from the URL
}
function error_callback( er ) {
top.location.href = 'location.php?err=1';
}
function showUI() {
// "let the user in right away"
}
if ( 'geolocation' in navigator ) {
navigator.geolocation.getCurrentPosition( getpos_callback, error_callback, {
enableHighAccuracy: true,
maximumAge: 300000, // 300 seconds = 5 min = max age of cached value to use
timeout: 8000, // 8 seconds
} );
showUI();
}
else { error(); }
No, there is no way to "spawn" a process on the background for this and let the user continue navigating=refresh the page.
The best way to do what you want is to make your web application a Single page application, meaning all actions are done by making AJAX requests.
In this case, you must only use AJAX requests for all actions:
and then change the page html.
Submitting the location is also done via AJAX request:
function getpos_callback( a ) {
//top.location.href = 'location.php?lat=' + a.coords.latitude + '&lon=' + a.coords.longitude;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
console.log('done');
}
}
xhr.open('GET', 'location.php?lat=' + a.coords.latitude + '&lon=' + a.coords.longitude, true);
xhr.send(null);
}
function error_callback( er ) {
// top.location.href = 'location.php?err=1';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
console.log('done');
}
}
xhr.open('GET', 'location.php?err=1', true);
xhr.send(null);
}
if ( 'geolocation' in navigator ) {
navigator.geolocation.getCurrentPosition( getpos_callback, error_callback, {
enableHighAccuracy: true,
maximumAge: 300000, // 300 seconds = 5 min = max age of cached value to use
timeout: 8000, // 8 seconds
} );
}
You can store the location in the session with an expired timestamp and if the user revisits the page, request it only if it has expired.
For keeping history and back button functionality for the browser, you can set the Url Hash for each view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With