簡介:
在微信小程序開發過程中,網絡請求是開發中最基礎也是最核心的需求,封裝一個穩定且可用性高的請求也顯得尤為重要。通常封裝的內容除了入參之外,更多的是請求中的異常處理。在處理 token 異常方面的做法,通過維護請求隊列,實現重發請求,減少 token 重復請求。
步驟:
- 正常業務請求
- 檢查該請求地址是否需要登錄后訪問,如果不需要,則直接訪問,該請求結束
- 如果需要,則判斷緩存Token是否存在,如果不存在,則直接跳轉登錄,如果存在,進入步驟4
- 請求后端接口,請求token未過期,則正常返回業務數據,如果請求token過期,則進入步驟5
- 調用Token刷新接口,刷新token過期,則直接跳轉登錄
- 刷新token沒有過期,則獲取token,并存入緩存 進入步驟7
- 在客戶無感知(無痛)情況下繼續請求最初的業務請求,將結果返回
需要注意:請求如果沒有限制處理,有多個請求同時到達,就會發起多個 updateToken 請求,其實我們并不想這樣,只需要請求一個updateToken即可,其他則直接排隊,等待第一個拿到后,直接使用
request1.js代碼
let isRefreshing = true; // 請求鎖
let pendings = []; // 請求列表
const pathArr = ['pages/buy-goods/index']; // 不需要登錄的路徑
const baseUrl = "http://192.168.0.112:9999";// 基礎路徑
function request({method, url, data, options = {
needLogin: true
}}) {
const token = wx.getStorageSync('tokenInfo')
const pages = getCurrentPages();
const router = pages[pages.length - 1]['route']; // 當前路由
if (pathArr.includes(router)) options.needLogin = false; // 當前路徑是否需要登錄
return new Promise((resolve, reject) => {
// 需要登錄 但是 token不存在 跳轉登錄
if (!token && options.needLogin) {
wx.redirectTo({
url: '/pages/login/login',
})
return
}
wx.showNavigationBarLoading();
wx.showLoading({
title: '數據加載中...',
mask: true
})
// 請求主體
wx.request({
url: baseUrl + url,
header:{
Authorization:token.access_token
},
method,
data,
success(res) {
let code = res.data.code
if (code == '9898') {
resolve(res.data)
} else if (code == '200') {
if (isRefreshing) {
updateToken();
isRefreshing = false;
pendings.push(() => {
resolve(request({method, url, data, options}))
})
}
} else {
resolve(res.data);
}
},
fail(err) {
reject(err);
},
complete() {
wx.hideNavigationBarLoading();
wx.hideLoading();
}
})
})
}
// 刷新token
function updateToken() {
const token = wx.getStorageSync('tokenInfo');
const userId = token.user_id;
const refreshToken = token.refresh_token;
wx.request({
url: baseUrl + '/user/refreshToken',
method: 'POST',
data: {
userId: userId,
refreshToken: refreshToken
},
success(res) {
let code = res.data.code
if (code == '200') {
wx.setStorageSync('tokenInfo', {
access_token: res.data.data.accessToken,
refresh_token: res.data.data.refreshToken,
user_id: res.data.data.userId,
});
pendings.map((callback) => {
callback();
})
isRefreshing = true;
} else {
toLogin();
}
}
})
}
// 前往登錄頁面 清空狀態
function toLogin() {
wx.showToast({
title: '登錄失效,請重新登錄',
icon: "none",
success: () => {
setTimeout(() => {
wx.redirectTo({
url: '/pages/login/login',
})
pendings = [];
isRefreshing = true;
}, 1200);
}
})
}
module.exports = {
request
};
業務js
import {
request
} from '../../request/request1.js';
Page({
/**
* 頁面的初始數據
*/
data: {
},
/**
* 生命周期函數--監聽頁面加載
*/
onLoad: function (options) {
const orderId = options.orderId;
this.queryOrderQuoteList(orderId);
},
async queryOrderQuoteList(orderId){
const res = await request({
method:"POST",
url:"/order-quote/queryOrderQuoteList",
data:{
orderId: orderId,
pageNum: 1,
pageSize: 10
}
});
console.log(res);
}
})
效果
正常業務請求
刷新token
繼續請求業務