# 7、请求等待机制
一般需要登录的小程序,运行后第一个请求的接口是登录,而其余接口需要等待登录接口完成后才能执行。
如果这个小程序只有一个页面/或者固定首页入口,我们可以将登录接口直接写到首页代码里,通过 js 代码 await 等方式,实现登录接口的前置。
await login();
1
但审批不同,审批有多个页面,且部分场景可以直接访问子页面(如发给用户的审批消息卡片),登录接口逻辑就需要写到根入口(如:App.vue)下.
// App.vue
<script>
export default {
onLaunch: function (option) {
console.log('App Launch', option)
// 登录
loginAndGetToken()
},
onShow: function () {
console.log('App onShow')
},
onHide: function () {
console.log('App onHide')
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
可这么一来,第一个页面的请求,就无法很好的判断登录接口是否完成,因为第一个访问页面 与 App.vue 的渲染是很快的,请求很可能在登录接口回来之前,就发出去了。
所以,我们需要一个请求等待机制,目的:其他接口需要在登录接口执行完之后再执行,机制:是在登录接口逻辑执行时,阻塞其他接口执行,登录接口执行完毕,该阻塞释放。
定义一个阻塞类
// blockRequest.js
/**
* 用于阻塞接口请求,某个接口请求处理完毕后才能请求其他接口的情况(比如登录
*/
class BlockRequest {
constructor() {
this._events = []
this.isBlocked = false
}
// 获取当前状态是否阻塞
getStatus() {
return this.isBlocked;
}
// 将状态至于阻塞
blockRequest() {
this.isBlocked = true
}
// 阻塞释放,并将已订阅的时间执行
freeRequest() {
this.isBlocked = false
this._events.forEach((func) => {
func && func()
})
this._events = []
}
// 订阅事件
pushEventlistener(listener) {
this._events.push(listener)
}
}
const blockRequest = new BlockRequest();
export default blockRequest;
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
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
在登录接口逻辑处前后,分别加上 “请求阻塞” 和 “阻塞释放”
// login.js
import blockRequest from './blockRequest';
await function loginAndGetToken() {
blockRequest.blockRequest(); // 请求阻塞
await login();
// ...todo (设置好token之类的)
blockRequest.freeRequest(); // 阻塞释放
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
request 请求前置方式配置如:
// request.js
import blockRequest from './blockRequest';
// 等待请求释放方法
const pendFree = async () => {
return new Promise((resolve) => {
// 订阅阻塞释放事件
blockRequest.pushEventlistener(() => resolve({}))
})
}
// 网络请求配置
const service = (url, method = 'GET', params = {}, header = {}) => {
return new Promise(async (resolve) => {
// 当前接口释放需要阻塞等待(ignoreBlock 是**白名单机制,登录接口需要在白名单中,否则登录接口也被阻塞**
if (!header.ignoreBlock && blockRequest.getStatus()) {
await pendFree(); // **阻塞释放后,才往下继续执行**
}
// todo ... 封装token等参数逻辑
bz.request({
...
})
})
}
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
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
从上面方法可以看出,我们只需在登录接口逻辑处和请求封装处添加上阻塞逻辑即可,页面上的请求逻辑不要添加额外逻辑,该怎么写就怎么写。
如此,在登录接口执行的时候,页面上的接口虽然会正常执行,但会一直处于前台 pending
状态,待登录接口执行后,才会发出。