解决 wx.getLocation 无法获取回调问题
wx.getLocation
是微信JS SDK提供的获取地理位置的能力,可通过调用微信客户端定位功能来获取用户GPS信息。
为了更好地提供个性化的推荐,许多情况下都要请求GPS定位信息。
生产环境有时会出现未能获取经纬度的反馈,尽管对应的设备定位权限已经开启。
针对用户反馈的case进行分析,捕获共性,最后发现此类问题的情景通常是页面刚加载便需要获取GPS信息。
因此,建议将获取GPS的方法放置在 config 接口注入权限验证配置 之后执行,以避免获取GPS信息失败。
wx.ready(function(){
// config信息验证后会执行 ready 方法,所有接口调用都必须在 config 接口获得结果之后,
// config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,
// 则须把相关接口放在 ready 函数中调用来确保正确执行。
// 对于用户触发时才调用的接口,则可以直接调用,不需要放在 ready 函数中。
wx.getLocation({
type: 'wgs84', // 默认为wgs84的 gps 坐标,如果要返回直接给 openLocation 用的火星坐标,可传入'gcj02'
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
}
});
});
对获取GPS方法进行时机调整后仍存在未收到getLocation回调的情况,继续深入分析。
最后,发现只有同一时间发起的第一个定位请求得到了回调,而其他几个则没有得到回调。
猜测:
getLocation在未完成当前GPS请求时,会忽略新进入的请求,那对调用方来说就丢失了回调请求。
方案:
封装 wx.getLocation
,利用Promise的异步特性,在当前GPS定位请求未完成时,新进入的执行请求会得到一个当前正在执行的Promise,直到当前GPS定位请求完成,所有进入的请求都将获得定位状态的变化通知。
/** @type {Promise<any> | null} */
let locationPromising = null;
function getLocation() {
/** 如果有 locationPromising 表示当前有进行中的请求,直接返回该请求。*/
if (locationPromising) return locationPromising;
locationPromising = new Promise((resolve, reject) => {
wx.getLocation({
type: "gcj02",
success: resolve,
fail: reject,
});
});
// 无论成功失败,都清理掉。
// 这里的catch为了防止重复抛出异步exception,异步exception由调用侧消化
locationPromising.catch(() => {}).finally(() => (locationPromising = null));
return locationPromising;
}