是否可以在后台从桌面浏览器获取 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 位置的最佳方式