当前位置: 首页 > news >正文

uniapp小程序无感刷新token

  • request.js
// request.js
import {getApptoken,getStoredApptoken
} from './tokenRequest' // 从合并模块导入// 全局配置
const MAX_RETRIES = 1 // 最大重试次数
const baseURL = 'https://your-api.com'// 请求队列和刷新状态
let requestsQueue = []
let isRefreshing = false// 核心请求函数
export const request = config => {return new Promise((resolve, reject) => {// 应用请求拦截器const processedConfig = requestInterceptor({baseURL,method: 'POST',needRefreshToken: true,retryCount: 0, // 记录重试次数...config})// 处理参数拼接(原URL有参数则用&,否则用?)const separator = processedConfig.url.includes('?') ? '&' : '?'const url = `${processedConfig.baseURL}${processedConfig.url}${separator}token=${processedConfig.apptoken || ''}`// 发起请求uni.request({...processedConfig,url,success: response => {// 应用响应拦截器responseInterceptor(response, processedConfig).then(resolvedData => resolve(resolvedData)).catch(err => reject(err))},fail: error => {console.error(`请求失败:${processedConfig.url}`, error)reject(error)}})})
}// 请求拦截器:统一处理请求前逻辑
const requestInterceptor = config => {config.header = {'Content-Type': 'application/json',...config.header}if (config.needRefreshToken) {const token = getStoredApptoken() // 使用合并模块的工具函数if (token) {config.token = token}}return config
}// 响应拦截器:统一处理响应后逻辑
const responseInterceptor = async (response, config) => {const {data,statusCode} = response// 处理成功响应if (statusCode === 200) {return data}// 处理401/400错误(token过期)if ((statusCode === 401 || statusCode === 400) && config.needRefreshToken) {// 检查是否超过最大重试次数if (config.retryCount >= MAX_RETRIES) {uni.showToast({title: '重试次数过多,请稍后再试',icon: 'none'})return Promise.reject(new Error('重试次数过多'))}// 如果正在刷新token,将请求加入队列等待if (isRefreshing) {return new Promise(resolve => {requestsQueue.push(() => resolve(request({...config,retryCount: config.retryCount + 1})))})}// 开始刷新tokenisRefreshing = truetry {// 获取新的tokenconst refreshSuccess = await getApptoken()if (!refreshSuccess) {return Promise.reject(new Error('获取新的token失败'))}// 重试原请求const retryResponse = await request({...config,retryCount: config.retryCount + 1})// 执行队列中所有挂起的请求requestsQueue.forEach(callback => callback())requestsQueue = []return retryResponse} catch (refreshError) {console.error('刷新token出错', refreshError)uni.showToast({title: '认证失败,请重新登录',icon: 'none'})return Promise.reject(refreshError)} finally {isRefreshing = false // 重置刷新状态}}// 其他错误处理return Promise.reject(new Error(`请求失败,状态码:${statusCode}`))
}// 封装常用请求方法
export const requestPost = (url, data, config = {}) => {return request({url,data,method: 'POST',...config})
}export const requestGet = (url, config = {}) => {return request({url,method: 'GET',...config})
}
  • tokenRequest.js
// tokenRequest.js// 应用配置
const infoObj = {appkey: process.env.ENV_TYPE === 'prod' ? 'C1A1140xxxxxxxxxxxxxxxxxxxxxxxxxxxx' :'3232313xxxxxxxxxxxxxxxxxxxxxxxxxxxx',appSecret: process.env.ENV_TYPE === 'prod' ? '34D7C4Exxxxxxxxxxxxxxxxxxxxxxxxxxxx' :'0A779D4xxxxxxxxxxxxxxxxxxxxxxxxxxxx',token: ''
}
const baseURL = 'https://your-api.com'// 基础请求(无拦截器)
const baseRequest = config => {return new Promise((resolve, reject) => {uni.request({method: 'GET',header: { 'Content-Type': 'application/json' },dataType: 'json',...config,success: response => resolve(response.data), // 直接返回datafail: error => reject(error)})})
}// 获取AppToken
export const getApptoken = () => {return new Promise((resolve, reject) => {const oldtoken = getStoredApptoken()const tokenUrl = `${baseURL}/getToken?token=${oldtoken}`baseRequest({ url: tokenUrl }).then(res => {if (res.token) {infoObj.token = res.tokenuni.setStorageSync('infoObj', JSON.stringify(infoObj))resolve(true)} else {uni.showToast({title: '更新token出错',icon: 'none'})resolve(false)}}).catch(err => {console.error('获取token接口失败', err)uni.showToast({title: '更新token接口出错',icon: 'none'})resolve(false)})})
}// 获取存储的AppToken
export const getStoredApptoken = () => {try {const stored = uni.getStorageSync('infoObj')return stored ? JSON.parse(stored).token : ''} catch (error) {console.error('获取存储的token失败', error)return ''}
}
  • xxx.vue
// 示例:调用POST接口(如需发送数据)
const submitData = async () => {try {const params = { name: 'test', age: 20 };// 调用POST接口(自动拼接token到URL)const res = await requestPost('/api/submit', params);console.log('提交成功', res);} catch (err) {console.error('提交失败', err);}
};
http://www.dtcms.com/a/271461.html

相关文章:

  • 数据结构之位图和布隆过滤器
  • ReactNative【实战系列教程】我的小红书 5 -- 文章详情(含轮播图 ImageSlider,点亮红心动画 Heart,嵌套评论等)
  • 【三维重建】一、设备分类
  • 优化 ECharts 多条折线:折线数据不完整导致的X轴日期错乱问题
  • 【面试精讲】I2C 子系统核心结构与常见问题深度解析
  • 【PTA数据结构 | C语言版】一元多项式求导
  • Redis-哨兵选取主节点流程
  • 操作系统核心技术剖析:从Android驱动模型到鸿蒙微内核的国产化实践
  • HashMap的Get(),Put()源码解析
  • CTFHub————Web{信息泄露[备份文件下载(网站源码、bak文件)]}
  • 微服务架构中数据一致性保证机制深度解析
  • [Backlog] 核心协调器 | 终端用户界面(TUI)实现 | 多分支任务冲突解决 | 测试验证体系
  • vue2中使用xgplayer播放流视频
  • 方差、协方差和协方差矩阵
  • 软件编码规范、运行时错误、安全漏洞与缺陷:解析及库博的检测能力
  • Dify 文本语意识别与自动补全工作流
  • VD6052系列 30V 200mA的低功耗稳压器芯片 适用12V/24V供电MCU
  • 腾讯0708面试手撕题:严格递增数字分割
  • 17-C#封装,继承,多态与重载
  • git配置密钥
  • MTK-系统设置Settings 开机累计时长源码分析
  • AI芯片产品经理:算力革命的架构师
  • Mysql底层专题(七)MVCC多版本并发控制机制
  • STM32-定时器输入捕获
  • 高级LoRA:面向垂直领域LLM的实战微调指南——LoRA合并、续训、堆叠,Checkpoint管理
  • 佰力博PEAI压电分析仪-精准测量压电材料d33系数
  • RAG实战指南 Day 11:文本分块策略与最佳实践
  • HCIP(综合实验)
  • 腾讯位置商业授权未来驾车ETA(批量)
  • Fluent许可配置常见问题