watchPosition 不按固定频率触发,仅在位置变化或精度提升时回调;需保存 watchId 并及时 clearWatch;PERMISSION_DENIED(code 1)不可重试,后台页面会节流或终止监听。

watchPosition 会一直触发回调,但不是“每秒一次”
它只在浏览器检测到位置变化(或精度提升)时才调用 successCallback,不会按固定时间间隔轮询。实际触发频率取决于设备传感器、网络定位质量、maximumAge 和 enableHighAccuracy 设置。
常见错误是以为能靠它实现“实时轨迹”,结果发现静止时没回调、移动缓慢时回调稀疏、GPS信号弱时长时间无更新。
-
maximumAge: 0强制不使用缓存位置,每次都要新获取(更耗电、更慢) -
enableHighAccuracy: true可能触发 GPS 模块,但 Android Chrome 在后台标签页中常被系统限制,iOS Safari 则可能直接降级为 IP 定位 - 没有设置
timeout时,失败可能无限等待,建议设为10000(10 秒)以内
watchPosition 返回的 watchId 必须保存,否则无法停止
watchPosition() 返回一个数字 ID(如 5),这是唯一能传给 clearWatch() 的凭证。一旦丢失,就再也停不掉这个监听 —— 即使页面跳转、组件卸载,它仍在后台运行,持续消耗电量和定位权限。
典型错误场景:在 React 组件里直接调用 watchPosition 但没把 watchId 存进 state 或 ref;Vue 中未在 onUnmounted 里调用 clearWatch(watchId)。
立即学习“前端免费学习笔记(深入)”;
- 推荐用
let watchId = null声明变量,在成功回调前先清空旧 ID:if (watchId) navigator.geolocation.clearWatch(watchId) - 不要依赖页面卸载事件(
beforeunload)来清理 —— 它在很多移动端浏览器中不可靠 - 多个并发监听需各自保存 ID,
clearWatch()不支持批量清除
errorCallback 里遇到 code === 1(PERMISSION_DENIED)不能重试
用户点“拒绝”后,watchPosition() 不会再弹窗请求权限,后续所有调用都会立刻进入 errorCallback,且 code 恒为 1。此时再反复调用毫无意义,还可能触发浏览器限流。
真正可重试的错误只有 code === 2(POSITION_UNAVAILABLE)和 code === 3(TIMEOUT),它们代表临时性问题。
- 遇到
code === 1,应停止监听,并引导用户手动去系统设置里开启定位权限 - 不要在 errorCallback 里自动重新调用
watchPosition(),除非你确认是超时或临时不可用 - 首次调用前可用
navigator.permissions.query({ name: 'geolocation' })预检状态,但注意该 API 在部分安卓 WebView 中不支持
watchPosition 在页面不可见时行为不稳定
Chrome(桌面/Android)、Safari(iOS)均会对后台标签页或最小化窗口中的 watchPosition() 进行节流甚至暂停:回调延迟增大、精度下降、部分机型直接停止触发。
这不是 bug,而是浏览器主动的资源保护策略。如果你的应用依赖持续后台定位(如物流追踪),必须明确告知用户“请保持页面前台运行”或引导使用 PWA + Background Sync 等替代方案。
- 可通过
document.hidden监听页面可见性,在隐藏时主动clearWatch(),显示时再重建 - 不要假设
watchPosition()能替代原生 App 的后台定位服务 - iOS Safari 在页面退到后台 30 秒后大概率终止所有 geolocation 监听,且不通知 JS



















