是否可以在后台从桌面浏览器获取 GPS 位置?

Posted

技术标签:

【中文标题】是否可以在后台从桌面浏览器获取 GPS 位置?【英文标题】:Is it possible to fetch GPS location from desktop browser in the background? 【发布时间】:2019-11-04 17:52:00 【问题描述】:

我有一个网络应用程序,它会询问用户他们的 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 秒)。即使使用移动设备,有时它也可能很慢。当用户只想继续使用该网站时,这几秒钟感觉就像是永恒。

我想做的是让用户立即进入,但以某种方式“生成一个任务”来向浏览器询问后台的位置,然后让它在后台将该位置传递给我,当位置已检索。

这可能吗?

【问题讨论】:

您能否提供有关您使用的框架/平台的更多详细信息? 【参考方案1】:

navigator.geolocation.getCurrentPosition 方法根据定义是异步的。它由 W3C 指定立即返回。详情可以查看the specification。

因此,您可以在调用getCurrentPosition之后立即调用“让用户进入”的函数,然后再调用成功回调。当你这样做时,getCurrentPosition 方法将已经在后台“生成一个任务”。

您的代码中的问题是您在收到回调后更改网页的 URL,在 getpos_callback 函数内。我建议您通过使用 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(); 

【讨论】:

【参考方案2】:

不,没有办法为此在后台“生成”一个进程并让用户继续navigating=刷新页面

做你想做的最好的方法是让你的网络应用程序成为一个Single page application,这意味着所有的动作都是通过发出AJAX请求来完成的。

在这种情况下,您只能对所有操作使用AJAX requests

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

然后更改页面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 Hash。

【讨论】:

【参考方案3】:

基本上,在我看来,对于您的情况,我认为最好使用 window.onload 事件。这意味着您在加载文档中的所有内容后加载您的地理位置。那是因为您可以让访问者在 GPS 初始化时浏览页面。

为了生成真正的线程,您可以使用 Worker,但 Worker 无权访问“导航器”对象的“地理定位”对象。但这在未来可能会改变。

异步函数可能适用于您的情况,因为它不会阻塞主线程。但是,我仍然认为最好在页面加载后运行 getCurrentPosition()。

setTimeOut() 可能不是最适合您的。虽然 setTimeOut() 可以延迟代码执行,并且在第一次调用时不会阻塞主线程,但它仍然会在稍后轮到执行时阻塞主线程。

给你一些参考:

Web workers - How do they work? - 这目前不适用于您的情况,但谁知道未来。

How to articulate the difference between asynchronous and parallel programming? - 异步函数不是真正的并行性,但可能适用于您的情况,因为它不会阻塞主线程。

How does setInterval and setTimeout work? - setTimeOut() 可能不适合您的用例,但值得一提。

https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition - watchPosition 的使用。如果您对 GPS 感兴趣,那么您将来可能会需要它。

window.onload 代码示例:

 <!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> 

【讨论】:

【参考方案4】:

您可以在 document.ready 中添加 giolocation 函数,在回调函数中您可以调用您的方法 像这样的

$(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')
);

我添加了设置时间来显示网站正在加载,而 giolocation 服务在后台运行

这是工作示例 https://jsfiddle.net/csbp2ey5/

【讨论】:

以上是关于是否可以在后台从桌面浏览器获取 GPS 位置?的主要内容,如果未能解决你的问题,请参考以下文章

从移动浏览器获取位置数据

Android API 30 及更高级别在后台获取 GPS 位置的最佳方式

是否可以直接从 appDelegate 获取 GPS 位置 ios8

是否可以仅在网络上获取 gps 坐标

是否可以通过将文件从桌面拖动到浏览器来上传文件

是否可以在 iPhone 上的 phonegap 应用程序中在后台跟踪 gps 位置?