解决 wx.getLocation 无法获取回调问题

972 阅读2分钟

解决 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;
}