我正在尝试使用 Geolocation watchPosition 连续监视用户的位置,但每 2 分钟只写入一次我的数据库。它目前每秒更新一次,这对我的服务器负载没有好处。我知道我需要以某种方式拆分功能。
<script>
function getLocation2() {
navigator.geolocation.watchPosition(
successCallback,
errorCallback_highAccuracy,
{maximumAge:0, timeout:30000, enableHighAccuracy: true}
); }
function errorCallback_highAccuracy(error) {
if (error.code == error.TIMEOUT)
{
navigator.geolocation.watchPosition(
successCallback,
{maximumAge:0, timeout:10000, enableHighAccuracy: false});
return;
}
}
function successCallback(position) {
var lat = position.coords.latitude;
var long = position.coords.longitude;
$.ajax({
type: 'POST',
url: './controller/al_gps_update.php',
data: { latitude: lat, longitude: long },
success: function(response) {
}
});
}
getLocation2();
var interval = 1000 * 60 * 2;
setInterval(getLocation2, interval);
</script>
我想连续使用 watchPosition 而不是 getCurrentPosition,因为我相信 GPS 需要一段时间才能获得准确的位置,所以我的理解是从已经运行的手表中提取数据会有所帮助。有时 GPS 位置会偏离。任何想法表示赞赏。
引用 MDN 文档:
方法Geolocation
用于注册一个处理函数,该函数将被自动调用每次设备的位置改变...watchPosition()
setInterval()
的方式工作(两者都返回一个数字 ID 并且都可以通过清除该 ID 来取消),但不是在每个间隔持续时间调用回调,而是根据变化调用回调设备的位置。
下面我创建了一个模板供您检查,它应该可以帮助您思考问题详细信息中不存在的一些问题——它包括内联评论,但基本概念是这样的:
您可以跟踪最近解决的位置
lastPosition
和最后一次成功上传位置数据的时间戳lastPostedTimestamp
作为程序状态。
使用该状态,您可以定义一个主要功能,该功能在运行时将:
确保
lastPosition
可用于上传并且上传之间所需的最小间隔已经过去,如果不满足任一条件则提前返回
存储位置的副本并取消其状态
尝试上传位置然后更新
lastPostedTimestamp
。如果上传失败,则将复制的位置恢复为状态,如果更新的位置尚未解决
每次解决新位置时,更新
lastPosition
的值,然后运行主要功能。
在每个上传间隔(例如 2 分钟),主要功能也会运行。
下面的代码是 TypeScript,但编译后的 JavaScript 可以在 TS Playground 链接的右侧面板中找到。
function handlePosition(position: GeolocationPosition): Promise<void> {
lastPosition = position;
return handleUpdate();
}
function handleGeoError(error: GeolocationPositionError): void {
switch (error.code) {
case error.PERMISSION_DENIED: {
// Stop watching:
navigator.geolocation.clearWatch(geoWatchId);
break;
}
case error.POSITION_UNAVAILABLE: {
// Handle (or don't)...
break;
}
case error.TIMEOUT: {
// Handle (or don't)...
break;
}
default: break;
}
}
/** @returns timestamp */
async function postPosition(position: GeolocationPosition): Promise<number> {
const response = await fetch(
"./controller/al_gps_update.php",
{
method: "POST",
headers: new Headers([['Content-Type', "application/json"]]),
body: JSON.stringify({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
}),
// Abort if upload takes too long:
signal: AbortSignal.timeout(20e3),
},
);
// Validate response if desired...
// Return current timestamp:
return Date.now();
}
async function handleUpdate(): Promise<void> {
if (
// There is no position:
!lastPosition
// Or not enough time has passed since the last post:
|| Date.now() <= (lastPostedTimestamp + postInterval)
) return;
const position = lastPosition;
lastPosition = null;
try {
lastPostedTimestamp = await postPosition(position);
} catch (cause) {
// Handle post failure (network error, timeoout, etc.)...
// If a newer position has not already been set in the meantime,
// restore the one that failed to be posted:
lastPosition ??= position;
}
}
const postInterval = 120e3;
let lastPostedTimestamp = Number.NEGATIVE_INFINITY;
let lastPosition: null | GeolocationPosition = null;
let geoWatchId = navigator.geolocation.watchPosition(
handlePosition,
handleGeoError,
{
enableHighAccuracy: true,
maximumAge: 0,
timeout: 120e3,
},
);
let updateTimerId = setInterval(handleUpdate, postInterval);