小程序 console 报错: Cannot read property 'scope.userLocation' of undefined;
客户反映小程序存在选择门店没有反应的情况,一开始怀疑是前一天修改了 js 代码有问题。用开发工具打开看了一下,点击选择门店的按钮时 console 栏确实有输出错误信息:Cannot read property 'scope.userLocation' of undefined;
。
选择门店涉及到用户位置信息授权 scope.userLocation
,以下是一般情况下用户授权的示例的代码:
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.userLocation" 这个 scope
wx.getSetting({
success(res) {
if (!res.authSetting['scope.userLocation']) {
wx.authorize({
scope: 'scope.userLocation',
success (res) {
// 用户已经同意小程序使用当前的地理位置功能,后续调用 wx.getLocation 接口不会弹窗询问
res && (res.authSetting["scope.userLocation"] ?
wx.getLoaction({
success: function (res) {
longitude = res.longitude, latitude = res.latitude;
}
}) : getApp().core.showToast({
title: "您取消了授权",
image: "/images/icon-warning.png"
}));
}
})
}
}
})
以上代码为还原代码,原始代码对获取授权的 getSetting()
和 authorize()
做了封装,但结构上面是一致的。
外层依次调用了 getSetting()
和 authorize()
方法,参数都是 res ,最后到获取位置信息时,又做了一次权限判断。这时候取到的参数 res 是 authorize()
返回的,我在外面两层的 success 回调里依次输出参数 res 的内容,getSetting()
获取到的是(未授权过位置权限):
{
authSetting: {}
errMsg: "getSetting:ok"
__proto__: Object
}
authorize()
获取到的是:
{
errMsg: "authorize:ok"
__proto__: Object
}
显然,authorize()
方法返回值是不包含 authSetting
对象的,代码原作者目的应该是获取到 getSetting
的返回值,但在第一次获取授权设置时,authSetting
是空的,也就是说,以这样的逻辑注定是获取不到授权后的授权设置的(因为这不单单是参数名重叠被覆盖的问题)。
原作者做二次判断 authSetting
的目的其实更多是完善逻辑,在用户取消时,弹出自定义模态框,提示用户取消了授权。这样的逻辑注定落空了,因为 authorize()
的 success 回调代表了用户已经同意了授权,判断逻辑分支无效。
既然判断逻辑没有意义,干脆去掉即可:
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.userLocation" 这个 scope
wx.getSetting({
success(res) {
if (!res.authSetting['scope.userLocation']) {
wx.authorize({
scope: 'scope.userLocation',
success (res) {
// 用户已经同意小程序使用当前的地理位置功能,后续调用 wx.getLocation 接口不会弹窗询问
wx.getLoaction({
success: function (res) {
longitude = res.longitude, latitude = res.latitude;
}
});
}
})
}
}
})
[notice]微信小程序 API 调用存在先后顺序,一般会嵌套调用。这时候需要注意返回值参数命名问题,如果变量名相同,上一级的返回值会被覆盖。[/notice]
但这个报错并不会导致选择门店功能无法使用,因为位置授权毕竟是成功了的。再次点击时,authSetting
中已经包含了 userlocation 这一项:
{
authSetting:{
scope.userLocation: true
__proto__: Object
}
errMsg: "getSetting:ok"
__proto__: Object
}
因为 res.authSetting['scope.userLocation']
已经存在,不需要再次授权,此时返回的 res
就是包含了 scope.userLocation
项的 getSetting()
返回值(源码中做了封装,在 getSetting
回调中判断是否已存在授权设置,存在则直接传值给调用封装的对象的回调 t.success && t.success(e);
)。
所以第二次点击选择门店是可以成功的,调试没有发现任何问题。那为什么存在这样的用户一直无法使用位置呢?
猜想是不是手机本身或者微信这个 app 的位置服务被关闭了。尝试关闭位置服务,果然调用失败,授权失败。
总结:调用位置服务时,要确保微信位置服务已启用。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。