我有一个网络应用程序,要求用户为他们的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秒)。即使使用移动设备,它有时也会变得迟钝。当用户只想继续使用网站时,这几秒钟感觉就像是永恒。
我想要做的是让用户立即进入,但不知何故“产生了一个任务”,向浏览器询问后台的位置,然后在检索到位置时,让浏览器在后台将该位置传递给我。
这个是可能的吗?
发布于 2019-11-15 06:17:13
根据定义,navigator.geolocation.getCurrentPosition方法是异步的。它由W3C指定立即返回。您可以查看the specification了解详细信息。
因此,您可以在调用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(); }发布于 2019-11-14 05:53:14
不,没有办法在后台“衍生”一个进程,让用户继续navigating=refresh页面。
做你想做的事情的最好方法是使你的web应用程序成为一个,这意味着所有的操作都是通过发出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
} );
}您可以使用过期的时间戳将该位置存储在会话中,如果用户重新访问该页面,则仅当该页面已过期时才请求该位置。
为了保留浏览器的历史记录和back按钮功能,您可以为每个视图设置Url Hash。
发布于 2019-11-13 16:57:22
基本上,在我看来,对于您的情况,我认为最好使用window.onload事件。这意味着您在加载文档中的所有内容后才加载地理位置。这是因为您可以让访问者在GPS初始化时浏览页面。
为了产生真正的线程,你可以使用Worker,但是Worker不能访问"navigator“对象的"geolocation”对象。但在未来,这种情况可能会改变。
异步函数可能适用于您的情况,因为它不会阻塞主线程。但是,我仍然认为在页面加载之后运行getCurrentPosition()是最好的。
setTimeOut()可能不是最适合您的方法。尽管setTimeOut()可以延迟代码执行,并且在第一次调用主线程时不会阻塞主线程,但在稍后执行主线程时,它仍然会阻塞主线程。
以下是一些参考资料:
Web workers - How do they work? -这个,目前不适用于你的情况,但谁知道未来。
How to articulate the difference between asynchronous and parallel programming? - async函数并不是真正的并行性,但可能适用于您的情况,因为它不会阻塞主线程。
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>
https://stackoverflow.com/questions/58698693
复制相似问题