service worker 无法离线获取实时地理位置,但可通过在线时预存定位信息并缓存区域资源实现离线差异化推送:在线时用 navigator.geolocation 获取经纬度存入 indexeddb,记录时间戳防过期;按城市等区域预缓存对应资源;离线 fetch 时从 idb 读取位置、匹配缓存路径返回,失败则降级至通用页。

Service Worker 本身无法在离线状态下获取实时地理位置(如 GPS 坐标),因为它在无网络时无法调用 navigator.geolocation 或第三方定位 API。但“基于地理位置的离线资源差异化推送”仍可实现——关键在于定位信息需提前获取并缓存,再结合 Service Worker 的缓存策略与请求拦截能力,在离线时按预存位置提供对应资源。
定位信息必须在在线时采集并持久化
用户首次访问时(在线),通过 navigator.geolocation.getCurrentPosition() 获取经纬度,并将结果存入 IndexedDB(推荐)或 Cache API 中的专用缓存(如 location-cache)。注意:需明确提示用户授权,且处理超时、拒绝、定位失败等边界情况。
- 建议同时记录时间戳,避免使用过期定位(例如 >24 小时)
- 可降级为 IP 地理粗略定位(服务端完成),作为补充方案
- 不要把定位数据存在
localStorage,因 SW 无法直接读取
用 Cache API 按区域预存差异化资源
在安装或激活阶段,Service Worker 可根据已知位置(如城市名、行政区编码)预缓存对应资源。例如:
- 用户位于「上海」→ 缓存
/offline/shanghai-notice.html、/assets/shanghai-map.jpg - 用户位于「成都」→ 缓存
/offline/chengdu-notice.html、/assets/chengdu-map.jpg
这些资源可在用户在线时由主页面触发 postMessage 通知 SW 开始缓存,或由后端下发区域配置清单驱动。
离线请求时动态匹配并返回本地资源
在 fetch 事件中,SW 不直接查地理位置,而是从 IndexedDB 异步读取最近一次有效定位(使用 event.waitUntil() 确保生命周期),再拼接对应资源路径,最后从 Cache API 中匹配响应:
self.addEventListener('fetch', event => {
if (event.request.destination === 'document' && !navigator.onLine) {
event.respondWith((async () => {
const loc = await getLatestLocationFromIDB(); // 自定义函数
const fallbackUrl = `/offline/${loc.city}-notice.html`;
const cache = await caches.open('offline-resources');
return cache.match(fallbackUrl) || cache.match('/offline/generic.html');
})());
}
});
注意:IndexedDB 查询是异步的,需用 waitUntil 防止 SW 提前终止;若定位未就绪,应有兜底资源(如全国通用页)。
更新机制与用户体验协同设计
地理位置可能变化(如用户出差),需支持主动刷新定位与资源:
- 主页面检测到网络恢复后,可重新定位并通知 SW 更新缓存
- SW 可监听
message事件,接收新位置及待缓存资源列表 - 在页面显示轻量提示(如“已为您切换至北京离线内容”),增强感知
不复杂但容易忽略:所有地理相关逻辑必须容错——定位失败、缓存缺失、区域无定制内容时,都应平滑回退到默认离线页,保障基础可用性。











