Geolocation API watchPosition 连续但每 2 分钟存储到 SQL 数据库

问题描述 投票:0回答:1

我正在尝试使用 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 位置会偏离。任何想法表示赞赏。

javascript geolocation
1个回答
0
投票

引用 MDN 文档

Geolocation
方法
watchPosition()
用于注册一个处理函数,该函数将被自动调用每次设备的位置改变...

这以类似于

setInterval()
的方式工作(两者都返回一个数字 ID 并且都可以通过清除该 ID 来取消),但不是在每个间隔持续时间调用回调,而是根据变化调用回调设备的位置。


下面我创建了一个模板供您检查,它应该可以帮助您思考问题详细信息中不存在的一些问题——它包括内联评论,但基本概念是这样的:

您可以跟踪最近解决的位置

lastPosition
和最后一次成功上传位置数据的时间戳
lastPostedTimestamp
作为程序状态。

使用该状态,您可以定义一个主要功能,该功能在运行时将:

  • 确保

    lastPosition
    可用于上传并且上传之间所需的最小间隔已经过去,如果不满足任一条件则提前返回

  • 存储位置的副本并取消其状态

  • 尝试上传位置然后更新

    lastPostedTimestamp
    。如果上传失败,则将复制的位置恢复为状态,如果更新的位置尚未解决

每次解决新位置时,更新

lastPosition
的值,然后运行主要功能。

在每个上传间隔(例如 2 分钟),主要功能也会运行。

下面的代码是 TypeScript,但编译后的 JavaScript 可以在 TS Playground 链接的右侧面板中找到。

TS游乐场

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);

© www.soinside.com 2019 - 2024. All rights reserved.