自从迷上了独立开发这个概念后,我一直在尝试开发 web app 来获取收益,但上线的几个 web app ,访问量大多都惨不仍睹。唯独有个实时海拔高度查询工具,这段时间还算有些起色。不知道我做对了什么,这个网页在必应国内版 “海拔查询” 关键词的搜索结果下排到了第一(虽然每天也仍然只有 80 个左右的用户 ip)。
但既然有了排名,我就打算乘热打铁,想着再优化完善一下,并且扩充一些内容,以期能进一步增加搜索引擎收录。但在这个过程中,我却发现开发这个工具所用到的 HTML5 的 Geolocation API ,没有办法提供稳定的服务。
实时海拔高度查询工具功能介绍及实现方式
首先交代一下,这是一个非常简单的应用,你可以在搜索引擎搜到很多这样的网页工具,功能是点击按钮后,显示出用户当前所在位置的海拔。
功能实现上也很简洁,可以说是一个纯前端应用——因为本身没有编写任何的服务端 api。整个查询过程分成两步:
- 第一步是获取地理位置,这一步使用 HTML5 的 Geolocation API ,去获取当前设备所在的经纬度。
- 第二步调用第三方(open-elevation)的 api ,根据 Geolocation API 获取得到的经纬度信息查海拔。
使用 Geolocation API 获取位置信息超时的问题表现
开始着手完善这个工具时,我发现急需要优化的第一个问题就是:在一些设备上,海拔查询经常会失败,而且重试也不起作用。开发这工具时,在我家里的开发机上开发完,测试能正常查询之后,我就将网页部署上线了。但后来在手机上使用的时候,却发现获取位置失败。
经过查看错误信息,我发现问题主要出在第一步——查询海拔失败。原因是调用 Geolocation API 的 navigator.geolocation.getcurrentposition 这个方法时,返回位置信息总是超时。
这让我感到不可思议。居然是是浏览器 API 实现的问题,我天真地以为 Geolocation 这个 HTML 5 的标准 API 是可靠的,但事实证明,它(至少在中国国内)并不可靠。
除了开发用的一台 win11 电脑之外,我在另一台 win10 电脑,和我的手机上,使用了这个工具,但后两者大部分情况下,getcurrentposition 都会超时。
用三台设备分别测试的情况是这样的:
- win11 台式电脑:屡试不爽,总能快速获取到位置信息。
- win10 台式电脑:极小概率能成功获取到位置信息
- 安卓手机:使用 chrome 或 edge 浏览器,点击按钮开始获取位置信息后,手机状态栏出现了定位图标,但位置信息获取还是超时。查看操作系统设置中定位服务的最近访问情况,发现浏览器没能成功访问定位服务(如果访问成功的话,会显示0分钟前),而如果打开百度地图、小红书等其它应用,发现都能正常访问到定位服务,唯独浏览器打开使用了 Geolocation API 的页面时访问不到。
一台 win10 的电脑有这个问题也就罢了,我心想大概是因为电脑没有 GPS,而需要使用 ip 定位等方案,在国内可能因为网络问题而访问不畅。
但问题是,我的手机是有 GPS 定位服务的,并且手机里的其他应用都是能够正常获取位置信息的,从这个表现来看,操作系统提供的定位服务是可靠的,所以我不能理解为什么手机使用浏览器中的这个 API 会失败。
一些发现
- 这个问题在网上没有得到广泛的讨论,没有针对性的回答,翻了很多年前的知乎帖子,大概有了一点数。
- 如何测试 Geolocation API 的能力: https://browserleaks.com/geo 是一个很好的展示浏览器 geolocation api 的页面。而且发现用这个工具成功获取到位置信息的概率要大。
- 如何尽可能确保使用 Geolocation API 能顺利访问到位置信息:1. 增加超时时间,我对比 https://browserleaks.com/geo 和其他位置获取网页工具的差异,发现其对这个 API 调用的区别在于:超时时间和是否使用 watch (提供了两个 API),browserleaks 设置的超时时间在 15s 左右,而其他大多数页面,超时时间为 10s
- 进一步,我发现市面上大多的查询经纬度的网页工具,都有这个问题。
备选方案
回退到使用 IP 进行定位
