一、小程序原生能力
微信利用了自己的賬號(hào)系統(tǒng),給每個(gè)小程序主體提供了拿到該用戶(hù)在當(dāng)前主體的唯一識(shí)別碼(open_id)的api: wx.login
wx.login({
success: function (res) {
if (res.code) {
callback(null, res.code)
// 拿到微信給的臨時(shí)登錄憑證code, 用這個(gè)code可以去服務(wù)器換成open_id
} else {
callback('登陸失敗!' + res.errMsg)
}
}
})
code換open_id必須通過(guò)服務(wù)器處理,需要使用到app_secret, 文檔地址:
https://developers.weixin.qq.com/miniprogram/dev/api/signature.html
二、一般登錄流程
- 服務(wù)器拿到code之后,去微信服務(wù)器換成用戶(hù)的當(dāng)前小程序的唯一id: open_id,并生成業(yè)務(wù)的登錄token,然后返回token給前端, 前端通常會(huì)將此token緩存在storage里,實(shí)現(xiàn)登錄狀態(tài)保持
let login = () => {
wx.request({
url: 'login',
code: code,
success: (data) => {
wx.setStorageSync('token', data.token)
}
})
}
- 前端在請(qǐng)求頭里帶上token
wx.request({
url: requestUrl,
data: data,
method: method,
header: {
'Authorization': `Bearer ${token}`
}
})
三、登錄過(guò)期重連
當(dāng)我們認(rèn)為登錄過(guò)期時(shí),將未完成的請(qǐng)求加入隊(duì)列,然后執(zhí)行登錄操作,登錄完成之后批量執(zhí)行隊(duì)列里的請(qǐng)求
// 用于存儲(chǔ)沒(méi)有complete的請(qǐng)求
const reqQueue = []
// 封裝一個(gè)通用的請(qǐng)求方法
let Rq = function (param, method, url, callback) {
let makeRequest = () = > {
let token = getStorageSync('token', token)
wx.request({
url: url,
data: param,
method: method,
header: {
'Authorization': `${token}`
},
complete: function (res) {
// 發(fā)現(xiàn)登錄過(guò)期
if (String(res.statusCode) === '401') {
// 往隊(duì)列里丟待執(zhí)行的函數(shù)
reqQueue.push(makeNowRequest)
login()
return
}
callback(null, res.data)
}
})
}
makeRequest()
}
修改login函數(shù),登錄之后執(zhí)行隊(duì)列的函數(shù)
let login = () => {
wx.request({
url: 'login',
code: code,
success: (data) => {
wx.setStorageSync('token', data.token)
// 執(zhí)行隊(duì)列里的等待函數(shù)
reqQueue.forEach((item) => {
item()
})
}
})
}
這里最關(guān)鍵的一步就是在401發(fā)生的時(shí)候,將當(dāng)時(shí)的函數(shù)執(zhí)行上下文存儲(chǔ)起來(lái),用于登錄重試后的處理。需要明白的是,在微信小程序里是沒(méi)有cookie的,做數(shù)據(jù)持久化依賴(lài)的是wx.setStorage,以及重試?yán)没卣{(diào)隊(duì)列的存儲(chǔ)和釋放來(lái)實(shí)現(xiàn)。