能否在桌面浏览器后台获取GPS位置信息?

6

我有一个Web应用程序,要求用户提供他们的GPS位置。使用类似于以下代码的标准代码可以很好地运行:

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
    } );
}

这里的问题是:在桌面浏览器上,确定位置可能需要相当长的时间(根据代码,每次需要4-6秒,甚至长达8秒)。即使在移动设备上,有时也会变得迟钝。当用户只想使用站点时,这些秒钟感觉像漫长的永恒。
我想要做的是让用户立即进入网站,但在后台“生成任务”以请求浏览器获取位置,并在检索到位置后在后台将该位置传递给我。
这是否可行?

你能提供一下你使用的框架/平台的更多细节吗? - akseli
4个回答

6

navigator.geolocation.getCurrentPosition方法在定义上是异步的。W3C规定它应该立即返回,您可以查看规范了解详细信息。

因此,在调用getCurrentPosition之后,在成功回调被调用之前,您可以简单地调用“让用户进入”的函数。当这样做时,方法getCurrentPosition将已经在后台“生成了一个任务”。

您的代码问题在于,在getpos_callback函数内收到回调后更改了网页的URL。我建议您通过使用JS更新UI状态而不是使用lat/lng参数重新加载页面来更改此行为。

重构您的代码后,它将如下所示:

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(); }

4

不,无法在后台“生成”进程并让用户继续“导航=刷新页面”。

实现您想要的最好方法是将您的Web应用程序制作为单页应用程序(Single page application),这意味着所有操作都通过进行AJAX请求来完成。

在这种情况下,您必须只使用AJAX请求执行所有操作:

  • 提交表单,
  • 登录,
  • 访问另一个视图
  • 等等

然后再更改页面HTML。

提交位置也通过AJAX请求完成:

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
    } );
}

您可以在会话中存储带有过期时间戳的位置,如果用户重新访问该页面,则仅在其到期时请求。

为了保持浏览器的历史记录和后退按钮功能,您可以为每个视图设置URL哈希


1
基本上,我认为对于你的情况,最好使用window.onload事件。这意味着在文档加载完成后再加载地理位置信息。这是因为您可以让访问者在GPS初始化时浏览页面。
要生成真正的线程,您可以使用Worker,但Worker无法访问“navigator”对象的“geolocation”对象。但这可能会在未来发生改变。
异步函数可能适用于您的情况,因为它不会阻塞主线程。然而,我仍然认为最好在页面加载后运行getCurrentPosition()。
setTimeOut()可能不适合您。尽管setTimeOut()可以延迟代码执行,并且在首次调用时不会阻塞主线程,但它在稍后执行时仍会阻塞主线程。
以下是一些参考资料: Web workers - How do they work?- 目前这对您的情况没有作用,但谁知道未来呢。

如何明确异步和并行编程之间的区别? - 异步函数不是真正的并行处理,但在某些情况下可能适用,因为它不会阻塞主线程。

setInterval和setTimeout如何工作? - setTimeOut()可能不适合您的使用情况,但值得一提。

https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition - 使用watchPosition。如果您涉及GPS,将来可能需要使用此功能。

Example window.onload code:

 <!DOCTYPE html>
<html>
<body>

<script>
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';
}

function getGPS(){
    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
        });
    }
}

/*
 * Attach getGPS to the window.onload event.
 *
 */
if ( window.addEventListener ) {
    window.addEventListener('load', getGPS);
} else {
    window.attachEvent('onload', getGPS);
}
</script>

</body>
</html> 


1

您可以在 document.ready 中添加地理位置功能,在回调函数中调用您的方法,类似于以下内容:

$(document).ready(function() {
 setTimeout(() => {
  if (navigator.geolocation) {
   navigator.geolocation.getCurrentPosition(function(position) {
    alert('This will call when you have giolocation Lat is ' + position.coords.latitude + ' Lon is ' + position.coords.latitude)
   });
  } else {
   alert("Browser does not support HTML5 geolocation.");
  }
 }, 500);
 alert('Rest of things loded in in background')
});

我已经添加了设置超时时间的代码,以便在后台运行地理位置服务时显示站点正在加载。以下是一个可用的示例链接:https://jsfiddle.net/csbp2ey5/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接