步骤
- 1、定义token的类型和初始化token
1
2
3
4
5
6
7
8
9
10
11
12
13let token = {
// token是由后端服务在用户登录时生成并返回给小程序,所以小程序端定义时需要了解后端需要传输什么在定义
}
// token管理器
const tokenManager = {
getToken(){
return token
},
setToken(tokenData){
return (token = {...token,...tokenData})
}
} - 2、封装好请求处理
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
28const _request = (url,data,method) => {
return new Promise((resolve,reject) => {
wx.request({
url,
data,
header: tokenManager.getToken(),
method,
succes(resp) {
if(resp.status.code === 502 || resp.statusCode === 500) {
reject({errMsg: '请求失败'})
return
}
const data = resp.data
if(data.err) {
const { result } = data
const msg = result.state.msg
reject({errMsg:msg || data.msg,data:result})
}else {
const result = resp.data
resolve(result)
}
},
fail(err) {
reject(err)
}
})
})
} - 3、继续封装网络请求和处理返回的数据格式,然后在登录的接口中调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const httpRequest = async(link,data={},method: 'GET',showLoading=false) => {
if(showLoading) {
wx.showLoading({
title:"请求中",
mask: true
})
}
const handleData = {...data}
if(link.cross){
handleData.cross = link.cross
}
const [error,response] = await _to(_request(link.url,handleData, method))
console.log(link.text, respone, error)
if(showLoading){
wx.hideLoading()
}
return Promise.resolve([error,response])
} - 4、统一封装和写好api请求,页面中直接调用请求和传参即可
1
2
3
4
5
6
7export const getApi = async(pramas) => {
const [err,res] = await httpRequest(apiurl,{pramas})
if(!err && res) {
return res.result
}
return null
} - 5、处理登录模块,定义一个判断登录状态的变量,默认为null
- 6、处理静默登录的逻辑并通过
wx.login()
从微信服务端获取code1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const _handleDefaultLogin = async () => {
const systemInfo = wx.getDeviceInfo() // 获取设备信息
const [networkErr,networkRes] = await _to(wx.getNetworkType()) // 获取网络类型
if(networkErr) throw new Error('获取网络失败')
const [wxLoginErr, wxLoginRes] = await _to(wx.login())
if(wxLoginErr) throw new Error('微信登录失败')
// 设置token
...
// 调用业务登录接口
const [loginErr,loginRes] = awiat httpRequest(loginlink,{code: wxLoginRes.code || '', ...token})
const loginData = loginRes.result
if(loginErr || !loginData) throw new Error(loginErr.errMsg)
// 从loginData中拿到服务端传来的token数据,sessionId 或sid二者一样,看服务断校验使用哪一个
// 继续设置token
// 全局存储用户信息
// 返回用户信息
} - 7、防止重复调用静默登录,处理静默登录判断,使用之前定义好的登录状态判断变量,因为静默登录每个页面都会触发才这样处理
1
2
3
4
5
6
7
8
9
10if(!_loginRecoed) {
_loginRecord = new Promise((resolve,reject) => {
_handleDefaultLogin()
.then(res => {resolve(res)})
.catch(err => {
_loginRecord = null
reject(err)
})
})
}- 如果全局只调用一次设置完token之后使用
wx.setStorageSync()
存储在缓存中,然后根据token的存在判断是否需要重新登录
- 如果全局只调用一次设置完token之后使用
- 8、之后在全局布局中去调用静默登录这个方法
优化:
判断promise的登录状态(并行请求,先获取先展示)
- 在全局封装一个登录状态,调用时如果没有登录状态就将静态登录的状态赋值给它
- 然后await等待事件成功才继续执行下面的语句,没有成功不执行,最后完成重置状态
重复登录问题:
- 在统一在登录逻辑哪里处理
- 在默认登录时设置登陆后缓存,缓存数据最好使用序列化,把类型变为string
- 写一个函数用来判断是否登录,获取缓存,判断有缓存,将数据反序列化后在设置token返回true
- 完成后在整个登录逻辑那里去调用该函数,判断是否为true,返回
登录校验问题:
- 在不需要登录的路径上传参数cross,然后到请求页面中返回时从路径拿到cross
- 有cross时需与之前的data的合并
- 之后在请求方法中判断不存在cross则进行原先判断静默登录状态是否登录,存在则请求结果返回
解决路径调用api时无提示,不报错问题:
- 在全局中使用函数和简单索引类型
- 通过泛型让K遍历T中的每一项,返回T时拿到K
- 使用时就有提示