不可避免的,我們需要在同一個(gè)頁面同時(shí)執(zhí)行多個(gè)異步的網(wǎng)絡(luò)請(qǐng)求,為了避免token短時(shí)間內(nèi)多次重復(fù)刷新,我們采取訂閱的方式解決這個(gè)問題。
大概思路:由第一個(gè)請(qǐng)求去執(zhí)行token的刷新,如果接下來還有其他的網(wǎng)絡(luò)請(qǐng)求,我們讓其等待執(zhí)行,待token刷新結(jié)束之后,通知其他請(qǐng)求繼續(xù)執(zhí)行。(ps:因?yàn)槲疫@里沒有調(diào)用實(shí)際的接口,所以對(duì)于函數(shù)中接口地址及參數(shù)都省略掉了,在實(shí)際使用過程中,需要在函數(shù)中加上需要的參數(shù))
第一步:創(chuàng)建一個(gè)NotificationCenter.js文件用來封裝訂閱流程
function NotificationCenter() {
let notification = {};
//是否正在獲取token
let isRequesting = false;
this.registerNotification = function(name) {
if (typeof notification[name] == 'undefined') {
//注冊(cè)通知
notification[name] = [];
} else {};
}
this.addNotification = function(name, func) {
if (typeof notification[name] != 'undefined') {
notification[name].push(func);
} else {}
}
this.distributeNotification = function(name, object) {
if (typeof notification[name] != 'undefined') {
notification[name].forEach((item) => {
item(object);
});
notification[name] = [];
}
}
}
module.exports = {
NotificationCenter: NotificationCenter
}
第二步:創(chuàng)建一個(gè)Networking.js用來封裝所有的網(wǎng)絡(luò)請(qǐng)求過程
import {NotificationCenter} from './NotificationCenter';
let center = new NotificationCenter();
center.registerNotification('token');
//請(qǐng)求數(shù)據(jù)
function requestData(success, failure) {
fetchToken((successObj)=>{
//在這里再執(zhí)行接下來的數(shù)據(jù)請(qǐng)求即可
//doNetWorking
success(successObj);
},(failObj)=>{
failure(failObj)
});
}
//判斷是否存在token
function fetchToken(success, failure) {
//這里根據(jù)實(shí)際情況去判斷是否有必要去請(qǐng)求或者刷新token。我這里用過期時(shí)間和緩存是否存在做一個(gè)樣例
let currentTime = Date.now();
let expires_in = wx.getStorageSync('expires_in');
let token = wx.getStorageSync('token');
if (token && currentTime < expires_in) {
success(token);
} else {
if (center.isRequesting) {
center.addNotification('token', function(item){
if (item.length > 0) {
success(item)
} else {
failure('獲取token失敗');
}
});
} else {
center.isRequesting = true;
refreshToken((successObj)=>{
//在這里將獲取的token以及其他相關(guān)信息緩存
success(successObj);
storageToken(successObj);
center.distributeNotification('token',successObj);
center.isRequesting = false;
},(failObj)=>{
failure(failObj);
center.distributeNotification('token',failObj);
center.isRequesting = false;
});
}
}
}
//緩存token到本地
function storageToken (obj) {
//將token緩存到本地
}
//刷新token
function refreshToken(success, failure) {
setTimeout(() => {
success('token123456');
}, 3000);
}
module.exports = {
requestData
}
第三步:在page中直接調(diào)用Networking.js中的requestData方法去執(zhí)行網(wǎng)絡(luò)請(qǐng)求即可
networking.requestData((successObj)=>{
console.log(successObj);
},(failObj)=>{
console.log(failObj);
});
networking.requestData((successObj)=>{
console.log(successObj);
},(failObj)=>{
console.log(failObj);
});
networking.requestData((successObj)=>{
console.log(successObj);
},(failObj)=>{
console.log(failObj);
});
可以發(fā)現(xiàn),無論同時(shí)執(zhí)行幾個(gè)請(qǐng)求隊(duì)列,都只會(huì)執(zhí)行一次token的刷新過程。