需求描述
一个部署在国外的项目,在国内访问有些国外站点资源速度太慢,或无法访问,因此单独部署了一台香港的服务器用于中国大陆用户访问
希望前端代码可以判断用户地区(主要是国内大陆用户),自动重定向到香港服务器的站点
实现方式分析
一、地理位置API
使用 HTML5 navigator.geolocation.getCurrentPosition()
方法用来获取用户设备当前位置,可以得到经纬度数据
if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else { console.log("该浏览器不支持获取地理位置。"); } function showPosition(position) { console.log(position.coords.latitude + ' , ' + position.coords.longitude); }
注意
出于隐私考虑,报告地理位置前会先请求用户许可。浏览器会弹框询问是否允许获取地理位置,只有允许后才能得到经纬度数据
测试结果
getCurrentPosition()
方法在 Ubuntu18 (台式机)上的 Chrome, Firefox 浏览器无法获取经纬度数据
Windows10 (台式机上的Win10虚拟机)上的 Chrome, Edge 浏览器可以获取到经纬度数据
Android 上的 Chrome, 自带浏览器 可以获取到经纬度数据
测试地址-菜鸟教程:developer.mozilla.org/zh-CN/docs/…
小总结
这种实现方式对于部分设备或者系统无法获取地位位置数据,可获取数据需要手动设置允许应用访问地理位置才行,得到的经纬度数据也无法直观用户地区,还需要再转换一下结果,此方案直接 PASS
二、判断用户IP
通过用户网络IP,使用第三方位置服务得到用户IP,经纬度,国家,城市地区等数据
1.腾讯位置服务
<script> // qq api callback function function f(res) { console.log(res) if (res.result.ad_info.nation === '中国') { console.log('china') } else { console.log(res.result.ad_info) } } </script> <script charset="utf-8" src="https://apis.map.qq.com/ws/location/v1/ip?key=xxx&callback=f&output=jsonp"></script>
使用 jsonp 方式输出实现,回调函数必须在API服务调用脚本上面,其他方式可以自行研究,代码在个人项目中有实现
注意
https://apis.map.qq.com/ws/location/v1/ip?key=xxx&callback=f&output=jsonp
链接里面的 key
参数需要自己注册一个腾讯开
发者账号,申请一个开发密钥,免费的, 因为有配额限制文档这里就不提供了(可以运行个人GitHub项目分析效果)
腾讯位置服务文档: lbs.qq.com/service/web…
2.搜狐位置服务
<script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> <script> document.write(returnCitySN['cip'] + ', ' + returnCitySN['cid'] + ', ' + returnCitySN['cname']); </script>
没有找到类似于腾讯位置服务的那种开发文档可以直接在浏览器访问地址查看定位结果,如下图,在个人项目中也有实现。
3.太平洋位置服务
http://whois.pconline.com.cn/ipJson.jsp
依然没有文档
直接在浏览器输入 url 得到结果,如下图,这里没有在个人项目中实现
小总结
也有其他服务商提供的免费服务,可以自行测试,参考链接中有人整理了好多
有些站点会有一个 language 的选项,不同的语言对应不同的站点,使用 localstorage 的方式记录用户最后选择的语言,用户再次访问时通过检测最后一次使用的语言自动重定向至对应站点。
优点: 通过调用第三方免费或付费服务可以不用再次转化数据得到用户地区,从而满足业务需求
缺点: 因为业务依赖于第三方服务,如果第三方服务不稳定或挂了,就影响业务功能了,不太靠谱
三、JavaScript 标准内置对象
// JavaScript standard built-in object const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone console.log(Intl.DateTimeFormat().resolvedOptions()) console.log(timeZone) 复制代码
Intl 对象是 ECMAScript 国际化 API 的一个命名空间,它提供了精确的字符串对比、数字格式化,和日期时间格式化
Intl.DateTimeFormat.prototype.resolvedOptions()
方法返回一个新对象,该对象的属性反映了语言环境以及在此DateTimeFormat
对象初始化期间计算出的日期和时间格式设置选项
timeZone
options参数中为此属性提供的值, 该值标识运行时的默认时区
MDN: developer.mozilla.org/zh-CN/docs/…
小总结
JavaScript 标准内置对象方式,相对前面两个类型的实现更简单靠谱
由于输出的是时区,这个 Intl.DateTimeFormat().resolvedOptions().timeZone
在国内输出结果是 Asia/Shanghai
, 在国内时间是北京时间为准,国际时区方面中国城市是上海,这个在系统安装选择国家地区的时候也会遇到,我安装 Ubuntu 的时候选择中国地区也是上海
我 Google, Baidu, Bing 搜索引擎来来回回好几遍,也没看到这么个方式,然后大神告诉我还有这么一个实现的方式,据说是大神在搜解决方案的时候,看到 StackOverflow 中有人弱弱的回复了一下,论和大神一起做事的重要性
项目实现源码
Github:github.com/gywgithub/v…
参考链接
developer.mozilla.org/zh-CN/docs/…
developer.mozilla.org/zh-CN/docs/…
developer.mozilla.org/zh-CN/docs/…