问题
I've got a test app that fetches lat/lng values from the HTML5 geolocation service. Unfortunately, it's firing at rather inconsistent time intervals, anywhere from 500ms to 10000ms. I've tried changing the maximimAge and timeout parameters for the watch but those don't seem to change anything. I'm testing it in Chrome as well as via a simple Cordova app on an Android Lollipop build. The code below simply displays the timestamp value of the watch to eliminate any other delays that could be causing the issue. It appears that the interval is close to a 1 second then 5 second repeating pattern. I've also tried placing the geolocation fetch function inside a setInterval function and it behaves with the same 1 and 5 second repeating interval.
<html>
<body>
<h1>Timestamp</h1>
<div id="mytimestamp"></div>
<button id="btnstopwatch">Stop GPS</button>
</body>
</html>
<script type="text/javascript">
var mytimestamp = document.getElementById("mytimestamp");
//start watching location
watchPositionId = navigator.geolocation.watchPosition(updateCompass,handleerror,{
enableHighAccuracy:true,
maximumAge:3000,
timeout:3000
});
function updateCompass(p)
{
mytimestamp.innerHTML = p.timestamp;
}
function handleerror(err)
{
if(err.code ==1)
{
//user said no
alert('Please allow access to GPS');
}
else
{
alert(err.code);
}
}
</script>
回答1:
Relating to watchPosition(), on the following link w3 says "the successCallback is only invoked when a new position is obtained .......implementations may impose limitations on the frequency of callbacks so as to avoid inadvertently consuming a disproportionate amount of resources."
What it means is that watchPosition() is waiting for events which will cause changes in position to happen, otherwise it does nothing. So watchPosition() will not be calling updateCompass() unless it sees the changes in position. Also, in regard watchPosition(), maximumAge and timeout parameters are related to the acquiring new position, and these parameters has nothing to do with how much times and when watchPosition() is called...
WatchPosition() prevents continuous calls to see if position changes or not, and reacts only if some events related to position changes occur, this help to save resources like battery. But if you really want to see the position, let's say every three second, no matter if position changed or not I think setting an interval will be good approach.
var watchPositionId;
//start watching location
setInterval(function () {
watchPositionId = navigator.geolocation.watchPosition(updateCompass, handleerror, {
enableHighAccuracy: true,
maximumAge: 3000,
timeout: 3000
});
}, 3000);
function updateCompass(p) {
mytimestamp.innerHTML = p.timestamp;
// if you have alert message it will counts seconds once you dismiss the alert,
//this may be part of the issue why you kept getting diffrent intervals.
//alert(p.timestamp);
navigator.geolocation.clearWatch(watchPositionId);
}
You mentioned that you tried to setInterval and it didn't work, so please note that I commented alert() in the code above because it caused me to have delays, without it the time stamp in html updates every 3000ms with an accuracy about 5ms.
The above approach works if you want to use watchPosition() because clearWatch() stoppes the watchPosition() and it further callbacks. Basically the code above initiates new watchPosition() every three seconds and kills it with clearWatch(). That is being said I think watchPosition() is not the best method to use in this approach unless you expect significant changes in position within this time interval. I would rather use getCurrentPosition() since it does the job and doesn't wait for changes in position.
var watchPositionId;
//start watching location
setInterval(function () {
watchPositionId = navigator.geolocation.getCurrentPosition(updateCompass, handleerror, {
enableHighAccuracy: true,
maximumAge: 3000,
timeout: 3000
});
}, 3000);
function updateCompass(p) {
mytimestamp.innerHTML = p.timestamp;
}
回答2:
I ended up changing the solution to use both geolocation as well as the deviceOrientationEvent. Using the geolocation event alone created a very 'jerky' response and the device orientation event smooths this out.
Here's the setInterval function set to fetch the geolocation every ten seconds:
window.onload = function()
{
//fetch new GPS info every 10000 milliseconds
window.setInterval(function ()
{
navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoFailure, {
enableHighAccuracy: true,
maximumAge: 0,
timeout: 30000 //large timeout to accomodate slow GPS lock on some devices
});
}, 10000); //update current location every ten seconds
};
On geo success:
function onGeoSuccess(location)
{
//call function to calculate bearing
var cluebearing = geo.bearing(currentlat, currentlng, cluelat, cluelng);
//call function to rotate arrow
rotateArrow(cluebearing);
}//end onGeoSuccess()
Function to fetch device orientation and process:
function rotateArrow(mybearing)
{
//Check for support for DeviceOrientation event
if(window.DeviceOrientationEvent)
{
//orientation listener
window.addEventListener('deviceorientation', function(event)
{
var myalpha = event.alpha; //rotation from north
//process orientation change
}//end deviceorientation listener
}
}//end rotateArrow()
On geo failure:
function onGeoFailure()
{
alert('Please turn on your phone\'s GPS');
}
来源:https://stackoverflow.com/questions/31764217/geolocation-watch-doesnt-fire-consistently