提供信息门户网站制作/网盘资源搜索神器
小程序中实现token过期重新登录再重新请求业务接口
该方法用于小程序token两个小时后过期,重新获取token再请求接口
1、新建一个封装请求接口文件,命名为request.js(我在utils文件夹下建request.js),代码如下:
let isRefreshing = true;
let subscribers = [];function onAccessTokenFetched() {subscribers.forEach((callback) => {callback();})subscribers = [];
}function addSubscriber(callback) {subscribers.push(callback)
}export class Http {constructor() {}request({url,data = {},method,header,callback = ''} = {}) {let baseUrl = "xxxxx" //后台请求接口的公共部分let _this = this;return new Promise((resolve, reject) => {uni.request({url: baseUrl + url,data,method,header: {"token": uni.getStorageSync('token'),"content-type": method == 'post' || method == 'POST' ?'application/x-www-form-urlencoded' : 'application/json; charset=utf-8'},callback,fail(res) {reject(res)},complete: res => {// callback token过期后重新请求接口,接口返回的数据if (callback) return callback(res.data);let statusCode = res.data.code;let errText = res.data.msg;// console.log(statusCode, 'statusCode')if (statusCode == 404) {console.log('接口不存在')} else if (statusCode == 401 || statusCode == 10002 ) {// 将需要重新执行的接口缓存到一个队列中addSubscriber(() => {_this.request({url,data,method,header,callback: resolve})})if (isRefreshing) {getNewToken(`${baseUrl}/token/getToken`, url, data).then(() => {// 依次去执行缓存的接口onAccessTokenFetched();isRefreshing = true;})}isRefreshing = false;} else if (statusCode == 200 || statusCode == 0 || statusCode == 1) {// 登录成功,抛出数据resolve(res.data)}else if (statusCode == 10004) {reject(res.data)}else if(statusCode == 30001 || statusCode == 30002){// 提示用户登录信息不全,需要获取用户信息uni.navigateTo({url:"/pages/login/login"})} else if (statusCode.startsWith('5')) {uni.showModal({content: '服务器报错,请重试!',showCancel: false});}}})})}
}// 获取token,token请求的接口通过形参传进来
const getNewToken = (url) => {return new Promise((resolve, reject) => {uni.login({success(res) {console.log(res)uni.request({url: url,method: 'POST',header: {"content-type": "application/x-www-form-urlencoded"},data: {code: res.code},success(res) {console.log(res, 'token')let r = res.data;console.log(r, 'r')// 将所有存储到观察者数组中的请求重新执行。if (r.code == 0) {const token = r.data;// 使用本地缓存,把token存起来uni.setStorageSync('token', token);resolve(res);}}})},fail(err) {reject()console.error('uni login fail', err);}});})
}
2、使用方法,与utils文件夹同级建一个新的文件夹api,在api文件夹下新建index.js文件,代码如下
import { Http } from '../utils/request.js';
export class Index extends Http {constructor() {super();} // 获取轮播图 data代表参数getBanner(data) {return this.request({url: '/getBanner',method: 'GET',data: data});}
}
3、再在api文件夹下新建一个js(banner.js)文件,用于引入index.js写的接口,代码如下
import {Index
} from './index.js';
const API = new Index();// 轮播图
export function getBanner(location_type) {return new Promise(resolve => {API.getBanner({location_type: location_type}).then(res => {resolve(res.data)})})
}
4、在页面中使用,代码如下:
import { getBanner } from '../../api/banner.js'
export default {data() {return {imgUrls: []};},onLoad(options) {// 请求轮播图接口getBanner(0).then(res => {this.imgUrls = res})},methods: { }
};