不可避免的,我们需要在同一个页面同时执行多个异步的网络请求,为了避免token短时间内多次重复刷新,我们采取订阅的方式解决这个问题。
大概思路:由第一个请求去执行token的刷新,如果接下来还有其他的网络请求,我们让其等待执行,待token刷新结束之后,通知其他请求继续执行。(ps:因为我这里没有调用实际的接口,所以对于函数中接口地址及参数都省略掉了,在实际使用过程中,需要在函数中加上需要的参数)
第一步:创建一个NotificationCenter.js文件用来封装订阅流程
function NotificationCenter() {
let notification = {};
//是否正在获取token
let isRequesting = false;
this.registerNotification = function(name) {
if (typeof notification[name] == 'undefined') {
//注册通知
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
}
第二步:创建一个Networking.js用来封装所有的网络请求过程
import {NotificationCenter} from './NotificationCenter';
let center = new NotificationCenter();
center.registerNotification('token');
//请求数据
function requestData(success, failure) {
fetchToken((successObj)=>{
//在这里再执行接下来的数据请求即可
//doNetWorking
success(successObj);
},(failObj)=>{
failure(failObj)
});
}
//判断是否存在token
function fetchToken(success, failure) {
//这里根据实际情况去判断是否有必要去请求或者刷新token。我这里用过期时间和缓存是否存在做一个样例
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以及其他相关信息缓存
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中直接调用Networking.js中的requestData方法去执行网络请求即可
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);
});
可以发现,无论同时执行几个请求队列,都只会执行一次token的刷新过程。