0%

改造微信小程序的地狱回调

微信的 API 经常会传入 success、fail 之类的回调函数,逻辑简单时还好,一旦复杂起来,简直就是回调地狱。还好小程序现在已经支持 async/await 了

基础知识

建议阅读以下文章了解基础知识,否则你可能会看不懂我在说什么

回调地狱

什么叫回调地狱,这就叫回调地狱,总共有 两个回调函数,三个Promise对象嵌套,你找全了吗。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// userInfos 是数据库中 userInfo 的集合
setUserInfo(event) {
wx.getSetting({
success: (res) => {
if (!!res.authSetting["scope.userInfo"]) {
wx.getUserInfo({
lang: 'zh_CN',
success: (res) => {
const userInfo = res.userInfo
wx.cloud.callFunction({
name: 'getOpenId'
}).then(res => {
userInfos.where({ _openid: res.result.openId }).count().then(res => {
if (res.total === 0) {
userInfos.add({ data: event.detail.userInfo }).then(() => {
Toast.success('注册成功')
wx.reLaunch({
url: '/pages/my/my',
})
})
} else {
Toast.success('登录成功')
wx.reLaunch({
url: '/pages/my/my',
})
}
})
})
},
})
} else {
Toast.fail('请允许')
}
},
})
},

分离嵌套

改造回调函数

最外层的 wx.getSetting 的回调函数开始改起

1
2
3
4
5
6
7
8
9
10
11
setUserInfo(event) {
wx.getSetting({
success: (res) => {
if (!!res.authSetting["scope.userInfo"]) {
// 授权了信息
} else {
// 没授权信息
}
}
})
}

分离

首先 wx.getSetting 这个方法分离出去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
setUserInfo(event) {
// res 是 wx.getSetting 方法的 success 回调方法中的 res 对象
if (!!res.authSetting["scope.userInfo"]) {
//授权了信息
} else {
//没授权信息
}
}

getSetting() {
wx.getSetting({
success: (res) => {

}
})
},

使用 Promise 对象

接着要怎么获得 success 回调方法中 res 对象呢?

这个时候就要使用 Promise 对象了,匿名函数中的resolvereject 会帮我们分别传出 成功失败 的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
setUserInfo(event) {
// res 是 wx.getSetting 方法的 success 回调方法中的形参
if (!!res.authSetting["scope.userInfo"]) {
//授权了信息
} else {
//没授权信息
}
}

getSetting() {
return new Promise((resolve, reject) => {
wx.getSetting({
success: (res) => {
resolve(res)
}
})
})
},

async/await 异步/等待

此时在 setUserInfo 里直接调用 this.getSetting() 的结果是 undefined

这是因为 wx.getSetting 是一个异步的 耗时操作 ,调用 success 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
setUserInfo(event) {
// res 是 wx.getSetting 方法的 success 回调方法中的形参
if (!!res.authSetting["scope.userInfo"]) {
//授权了信息
} else {
//没授权信息
}
}

getSetting() {
return new Promise((resolve, reject) => {
wx.getSetting({
success: (res) => {
resolve(res)
}
})
})
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
async setUserInfo(event) {
const setting = await this.getSetting()
if (!!setting["scope.userInfo"]) {
//授权了信息
} else {
//没授权信息
}
}

getSetting() {
return new Promise((resolve, reject) => {
wx.getSetting({
success: (res) => {
resolve(res.authSetting)
},
fail: (res) => {
reject(res)
}
})
})
},

分离 Promise 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
async setUserInfo(event) {
const setting = await this.getSetting()
if (!!setting["scope.userInfo"]) {
// Promise
wx.cloud.callFunction({
name: 'getOpenId'
}).then(res => {
// 接着怎么做
})

} else {
//没授权信息
}
}

分离后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
async setUserInfo(event) {
const setting = await this.getSetting()
if (!!setting["scope.userInfo"]) {
const _openid = await this.getOpenId()
// 接着怎么做

} else {
//没授权信息
}
},

async getOpenId() {
try {
const res = await wx.cloud.callFunction({ name: 'getOpenId' });
return res.result.openId;
}
catch (error) {
return error;
}
},

改造结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
async setUserInfo(event) {
const setting = await this.getSetting()
// 是否授权了用户信息
if (!!setting["scope.userInfo"]) {
const userInfo = await this.getUserInfo()
const url = '/pages/my/my'
// 是否注册过
if (!await this.isRegistered()) {
// 没注册就插入一条
await userInfos.add({ data: userInfo })
}
wx.reLaunch({ url })
} else {
Toast.fail('请允许')
}
},

/**
* 获取用户设置
*/
getSetting() {
return new Promise((resolve, reject) => {
wx.getSetting({
success: (res) => {
resolve(res.authSetting)
},
fail: (res) => {
reject(res)
}
})
})
},

/**
* 获取用户信息
*/
getUserInfo() {
return new Promise((resolve, reject) => {
wx.getUserInfo({
lang: 'zh_CN',
success: (res) => {
resolve(res.userInfo)
},
fail: (res) => {
reject(res)
}
})
})
},

/**
* 获取 openid
*/
async getOpenId() {
try {
const res = await wx.cloud.callFunction({ name: 'getOpenId' })
return res.result.openId;
}
catch (error) {
return error;
}
},

/**
* 是否已注册
*/
async isRegistered() {
const _openid = await this.getOpenId()
try {
const res = await userInfos.where({ _openid }).count()
return res.total
}
catch (error) {
return error
}
}