优秀设计案例网站,成品在线视频免费入口,网站收录不好的原因,四川建设网共享平台概述 封装的网络请求库#xff0c;主要用于处理 API 请求并支持自动处理 token 过期 和 token 刷新#xff0c;适用于需要身份验证的应用场景#xff0c;特别是在移动端中。 主要功能
自动附加 Token 在每个请求中自动附加 Authorization 头部#xff0c;使用存储的 acces…概述 封装的网络请求库主要用于处理 API 请求并支持自动处理 token 过期 和 token 刷新适用于需要身份验证的应用场景特别是在移动端中。 主要功能
自动附加 Token 在每个请求中自动附加 Authorization 头部使用存储的 accessToken。如果某个请求不需要 Token则可以通过设置 isToken: false 来排除。 Token 过期自动刷新 当请求返回提示 accessToken 过期时自动尝试使用 refreshToken 刷新 accessToken在刷新过程中新的请求会被放入一个队列中等到 refreshToken 成功后再依次重试 请求重试机制 当 accessToken 刷新成功后队列中的所有待处理请求都会自动重发如果 refreshToken 刷新失败跳转到登录页面让用户重新登录。 统一的请求和响应处理 请求的 Content-Type 和 Accept 头部统一设置统一处理服务器返回的状态码若返回 200 且不含 ErrType: -10011则正常返回数据否则进行相关的错误处理 代码概览
refreshToken 函数 用于发送请求以刷新 accessToken通过 refreshToken 获取新的 accessToken并保存在本地若成功返回新的 accessToken若失败返回错误信息。 request 函数 封装了 uni.request 请求方法提供了 GET、POST 请求支持。 检查是否有有效的 accessToken如果有自动将其附加到请求头的 Authorization 中如果请求参数中包含 params则自动将其转换为查询字符串附加到 URL 中在请求成功时判断返回数据的 ErrType 是否为 -10011表示 accessToken 过期若过期则调用 handleTokenExpiration 函数刷新 Token handleTokenExpiration 函数 处理 accessToken 过期的逻辑避免在刷新 Token 的过程中发起多次刷新请求如果当前没有刷新请求正在进行则调用 refreshToken 函数尝试刷新 Token并将待重试的请求保存在队列中如果刷新 Token 成功则重试队列中的请求重新发送如果刷新 Token 失败清空队列并跳转到登录页面 isRefreshing 和 requestQueue isRefreshing 用于确保只有一个刷新请求在进行避免并发刷新 Token 的情况requestQueue 用于存储等待 Token 刷新完成后的请求确保刷新完成后再逐一处理这些请求 工作流程 用户首次登录时后端会返回 accessToken 和 refreshToken后续的 API 请求都会自动附带 accessToken当 accessToken 过期时后端返回 ErrType: -10011触发 handleTokenExpirationhandleTokenExpiration 检查是否正在进行刷新操作如果没有则开始刷新并保存待重试的请求刷新完成后重试这些请求确保请求使用最新的 accessToken Request.js
import store from /store;
import config from /common/config;
import { getToken, getRefreshToken, setToken } from /common/auth;
import { tansParams } from /common/index;let timeout 10000;
const baseUrl config.baseUrl;const refreshToken () {return new Promise((resolve, reject) {uni.request({method: post,url: ${baseUrl}/auth/refresh,data: { refreshToken: getRefreshToken() },header: { Content-Type: application/json },}).then((response) {if (response.statusCode 200 response.data.accessToken) {setToken(response.data.accessToken);resolve(response.data.accessToken);} else {reject(刷新令牌失败);}}).catch((error) {reject(error);});});
};const request (config) {const isToken (config.headers || {}).isToken false;config.header config.header || {};if (getToken() !isToken) {config.header[Authorization] Bearer getToken();}if (config.params) {let url config.url ? tansParams(config.params);url url.slice(0, -1);config.url url;}config.header[Content-Type] application/x-www-form-urlencoded; charsetUTF-8;config.header[Accept] application/json, text/javascript, */*; q0.01;return new Promise((resolve, reject) {uni.request({method: config.method || get,timeout: config.timeout || timeout,url: config.baseUrl || baseUrl config.url,data: config.data,header: config.header,dataType: json,}).then((response) {if (response.statusCode 200) {//登录过期if (response.data.ErrType -10011) {// Access Token 过期handleTokenExpiration(config, resolve, reject);} else {resolve(response.data);}} else {reject(服务器连接异常);}}).catch((error) {reject(error);});});
};let isRefreshing false; // 防止多次刷新
let requestQueue []; // 队列存储待重试的请求const handleTokenExpiration (config, resolve, reject) {if (!isRefreshing) {isRefreshing true; // 开始刷新refreshToken().then((newToken) {isRefreshing false;// 刷新成功后重试队列中的请求requestQueue.forEach((callback) callback(newToken));requestQueue []; // 清空队列// 重新发送当前请求resolve(request({...config,header: {...config.header,Authorization: Bearer newToken,},}));}).catch((error) {isRefreshing false;requestQueue []; // 清空队列// 刷新失败跳转到登录页面uni.reLaunch({url: /pages/login,});reject(登录已过期请重新登录);});} else {// 如果已经在刷新将请求加入队列requestQueue.push((newToken) {resolve(request({...config,header: {...config.header,Authorization: Bearer newToken,},}));});}
};export default request;