昨天在开发微信小程序的时候出现了个问题,是这样的:
我需要获取定位信息,传给后端,获取范围内的订单,接单之前也需要再次获取定位获取最新定位信息和自己的信息一起传递过去
结果就出现了这样的情况:
我就蒙了!我就去查看官方文档了:
官方传送门
文档是这么写的
我们去看相关公告
相关公告传送门
简而言之就是
1.在基础库2.17.0版本以上 都会对wx.getLocation进行限制
2.开发和体验版30秒内调用有效,30秒内会返回错误
3.对正式版不会报错,只不过30秒内返回的数据还是第一次获取的数据
面对上面的公告来说,如果你不用频繁调用wx.getLocatio获取定位来说还是可以使用的,就比如初始化 为了获取所在地理位置
这个限制无论是使用上还是测试的时候都是很不友好的
所以说我们就需要用官方提供的另一个方法 wx.onLocationChange
让我们看一下文档
大致意思就是 可以实时监听地理位置变化 传递的数据是一个回调函数 用于接收改变后的地理信息,还需结合 wx.startLocationUpdate使用。
简单理解就是 我需要先打开定位监听wx.startLocationUpdate 这样就可以监听到 使用wx.onLocationChange传递的回调函数接收值,如果不需要的话就用
wx.offLocationChange 关闭定位监听
为了提高代码复用率我们把这个获取定位的功能封装成模块吧
首先我们需要新建一个js文件
我们就叫
location.js放在你想放在的地方
先定义一个函数方法
我们这里叫做authorization并且导出,在里面写一个try-catch用于做错误的处理(这里的错误一般来说是没有开权限导致的)
export const authorization = () => { try{ //运行定位 }catch{ //处理错误 没有开定位权限的处理 } }
我们定义一个方法用于获取定位(主要的函数) 叫做getWxLocation
const getWxLocation = () => { //提示定位中 wx.showLoading({ title: '定位中...', mask: true, }) //运用promise 同步接收获取的值 return new Promise((resolve, reject) => { //定义接收定位信息的函数 let _locationChangeFn = (res) => { //当监听到了定位信息的数据 console.log('location change', res) //返回定位数据 resolve(res) wx.hideLoading() //关闭监听 wx.offLocationChange(_locationChangeFn) } //开启定位服务 wx.startLocationUpdate({ type: 'gcj02', success: (res) => { //开启成功后启动监听 传递回调函数 wx.onLocationChange(_locationChangeFn) }, fail: (err) => { console.log('获取当前位置失败', err) wx.hideLoading() //返回错误 reject() } }) }) }
把这个函数放在刚开始的那个函数里
这里使用async - await 异步转同步
export const authorization = async () => { try{ //运行定位函数 //把定位信息return出去 return await getWxLocation(); }catch{ //处理错误 没有开定位权限的处理 } }
定义没有开定位权限的函数
const toSetting = () => { return new Promise((resolve, reject) => { //调起客户端小程序设置界面,返回用户设置的操作结果 wx.openSetting({ success(res) { console.log(res) if (res.authSetting["scope.userLocation"]) { // res.authSetting["scope.userLocation"]为trueb表示用户已同意获得定位信息,此时调用getlocation可以拿到信息 let locationRes = await getlocation() resolve(locationRes) } }, fail(err) { reject() } }) }) }
放在主函数里
export const authorization = async () => { try{ //运行定位函数 //把定位信息return出去 return await getWxLocation(); }catch{ //处理错误 没有开定位权限的处理 wx.showModal({ title: '温馨提示', content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?', success: function (res) { if (res.confirm) {//这里是点击了确定以后 console.log('用户点击确定') toSetting() } else {//这里是点击了取消以后 console.log('用户点击取消') } } }) } }
调用就是引入
const { authorization } = require('../../../utils/location')
使用
let res = await authorization() console.log(res)
这样就可以了,不会做限制!!
完整代码
//这个函数是一开始点击事件触发的: export const authorization = async () => { try { return await getWxLocation() //等待 } catch (error) { wx.showModal({ title: '温馨提示', content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?', success: function (res) { if (res.confirm) { //这里是点击了确定以后 console.log('用户点击确定') toSetting() } else { //这里是点击了取消以后 console.log('用户点击取消') } } }) return } } const getWxLocation = () => { wx.showLoading({ title: '定位中...', mask: true, }) return new Promise((resolve, reject) => { let _locationChangeFn = (res) => { console.log('location change', res) // Storage.set('userLocation', res) resolve(res) wx.hideLoading() wx.offLocationChange(_locationChangeFn) } wx.startLocationUpdate({ type: 'gcj02', success: (res) => { console.log(res); wx.onLocationChange(_locationChangeFn) }, fail: (err) => { console.log('获取当前位置失败', err) wx.hideLoading() reject() } }) }) } const toSetting = () => { return new Promise((resolve, reject) => { //调起客户端小程序设置界面,返回用户设置的操作结果 wx.openSetting({ success(res) { console.log(res) if (res.authSetting["scope.userLocation"]) { // res.authSetting["scope.userLocation"]为trueb表示用户已同意获得定位信息,此时调用getlocation可以拿到信息 let locationRes = await getlocation() resolve(locationRes) } }, fail(err) { reject() } }) }) }
点个关注支持一下我吧