uniapp 微信小程序 封装axios 包含请求拦截、响应拦截、无感刷新令牌功能

本文介绍了在uniapp项目中如何使用axios进行网络请求,并实现令牌的无感刷新功能,包括axios的安装配置,以及自定义请求封装文件request.js中处理令牌过期和刷新的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
1、为什么不适用uniapp自带的请求功能?
答:uniapp自带的请求功能,再刷新了令牌后,重新请求返回的数据无法返回给发起请求的方法。也就是说,刷新令牌后重新发起的请求和第一次发起请求的方法是割裂的。
2、封装文件中,我设置了无感刷新令牌功能。我后台的判断逻辑是,当前端请求的令牌过期时间和当前时间比小于10分钟时,刷新令牌。
 

一、安装axios
1.1、使用HBuilder打开uniapp项目,点击视图->显示终端,打开npm操作页面。
1.2、如果项目中还没有“package.json”文件,请先初始化项目。

npm init -y

1.3、安装axios,建议锁定低版本(使用uniapp-vue3版本时,axios的版本需要0.26.0以下)。

npm i axios@0.26.0

 1.4 在main.js中配置axios

import axios from 'axios'//引入axios
import * as request from '@/common/api/request.js'//自定义请求封装文件
Vue.prototype.$http = request //封装的请求方法

// 解决uniapp 适配axios请求,避免报adapter is not a function错误
// 此配置也可以放在自定义请求封装文件中(例如 request.js)
axios.defaults.adapter = config => {
	return new Promise((resolve, reject) => {
		let settle = require('axios/lib/core/settle');
		let buildURL = require('axios/lib/helpers/buildURL');
		uni.request({
			method: config.method.toUpperCase(),
			url: config.baseURL + buildURL(config.url, config.params, config.paramsSerializer),
			header: config.headers,
			data: config.data,
			dataType: config.dataType,
			responseType: config.responseType,
			sslVerify: config.sslVerify,
			complete: function complete(response) {
			
				response = {
					data: response.data,
					status: response.statusCode,
					errMsg: response.errMsg,
					header: response.header,
					config: config
				};
				settle(resolve, reject, response);
			}
		})
	})
}

二、自定义请求封装文件 request.js,我的文件路径是 /根目录/common/api/request.js。

import axios from 'axios' // 引入axios
import store from '@/store/index.js'//引入store仓库

function getToken() { //获取令牌
	let token = store.state.accountValue.accessToken //store仓库中的令牌
	if (!token) { //令牌不存在,显示登录弹窗
		openLoginDialog()
	}
	return token
}

//令牌过期,刷新令牌请求
function refreshToken() {
	return service.get('/account/user/refresh/login').then(res => res)
}

//设置store及微信缓存中的账号信息
function setAccountInfo(accountInfo) {

	store.commit('accountValue/SET_ACCOUNT_INFO', accountInfo) //修改store中的账号信息
	//存储账号信息到微信缓存中
	wx.setStorage({
		key: "userInfo",
		data: JSON.stringify(accountInfo)
	})
}

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const baseUrl = store.state.constantValue.hostUrl + store.state.constantValue.port //域名/地址公共前缀
const appid = store.state.constantValue.appid //小程序的appid
const requestTimeout = store.state.constantValue.requestTimeout //默认的请求超时时间,单位毫秒
const service = axios.create({
	baseURL: baseUrl, //axios的默认请求地址前缀
	timeout: requestTimeout //默认的请求超时时间,单位毫秒
})

let requests = [] // 重试队列数组,把需要刷新令牌的请求都放入这个数组中,每一项将是一个待执行的函数形式

let common = {//默认的请求配置信息
	data: {},
	header: {
		"Content-Type": "application/json",
		"Content-Type": "application/x-www-form-urlencoded"
	},
	method: "GET",
	dataType: "json"
}


// 请求拦截器
service.interceptors.request.use(
	config => {

		// 每次发送请求之前判断vuex中是否存在token
		// 如果存在,则统一在http请求的headers都加上token,这样后台根据token判断你的登录情况
		// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
		config.method = config.method || common.method;
		if (config.method !== 'GET') {
			config.data = config.data || common.data;
		}
		config.dataType = config.dataType || common.dataType;
		config.header = config.header || common.header;

		if (config.header.NeedToken === 'NEED') { //如果需要访问令牌
			const token = getToken();
			!isNull(token) && (config.headers.Authorization = 'Bearer ' + token);
		}

		return config;
	},
	error => {
		return Promise.error(error);
	});


// 响应拦截器
service.interceptors.response.use(
	response => {

		// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
		// 否则的话抛出错误
		if (response.status === 200) {

			let code = response.data.code //code为自定义的后台响应code

			if (code === 20009 || code === 20010) { //未登录或者登录异常,需要重新登录时
				openLoginDialog()//打开登录弹窗
				return Promise.resolve(response.data); //返回响应结果
			} else {

				if (code === 20017) { //后台要求刷新令牌

					const config = response.config

					if (!store.state.constantValue.isRefreshing) { //如果正在刷新令牌状态为false

						//设置正在刷新令牌状态为true,进入更新令牌阶段
						store.commit('constantValue/SET_IS_REFRESHING', true)

						//获取刷新令牌请求
						return refreshToken().then(res => {

							if (res.code === 20000) {

								// 刷新令牌成功,设置store及微信缓存中的账号信息
								const accountInfo = res.data
								setAccountInfo(accountInfo)

								//已经刷新了令牌,重新发起重试队列数组中的请求
								requests.forEach(cb => cb(accountInfo.accessToken))
								// 完成后清空这个数组
								requests = []

								//重置当前请求的配置,重新发起请求
								config.headers.Authorization = 'Bearer ' + accountInfo.accessToken
								config.baseURL = baseUrl //axios的默认请求地址前缀
								config.timeout = requestTimeout //默认的请求超时时间
								return service(config) //重新发起请求,返回的就是当前请求
							} else {
								openLoginDialog()//打开登录弹窗
							}
						}).catch(rej => { //令牌刷新发生错误
							openLoginDialog()//打开登录弹窗
						}).finally(() => {
							//完成之后设置正在刷新令牌状态为false
							store.commit('constantValue/SET_IS_REFRESHING', false)
						})
					} else { //如果正在刷新令牌状态为true

						if (config.header.NeedToken === 'NEED') { //请求需要令牌

							// 返回一个未执行resolve的promise
							return new Promise((resolve) => {
								// 将resolve放进重试队列数组,用一个函数形式来保存,等令牌刷新后直接执行
								requests.push((token) => {
									config.headers.Authorization = 'Bearer ' + token
									resolve(service(config))
								})
							})

						}
					}
				}
				return Promise.resolve(response.data) //返回响应信息
			}
		} else { //状态码不为200时
			return Promise.reject(response.data) //返回响应异常信息
		}
	},
	error => {
		return Promise.reject(error) //返回响应错误信息
	}
);

export default service;

### uniapp 微信小程序 使用 Axios 发送 请求 示例代码 在 UniApp 开发环境中,虽然默认提供了 `uni.request` 方法用于发起 HTTP 请求,但也可以集成第三方库如 Axios 来简化网络请求操作。为了使 Axios 能够正常工作于微信小程序环境内,需先安装适用于小程序Axios 版本。 #### 安装依赖 首先,在项目根目录下执行命令来安装适合小程序使用的 Axios: ```bash npm install axios-miniprogram-fix ``` 此版本解决了原生 Axios 不支持小程序环境的问题[^1]。 #### 配置 Axios 实例 创建一个新的 JavaScript 文件(例如 `http.js`),用来初始化 Axios设置全局配置项: ```javascript import axios from 'axios-miniprogram-fix'; const service = axios.create({ baseURL: '', // 设置统一的基础路径 timeout: 5000, // 请求超时时间 }); // 添加请求拦截器 service.interceptors.request.use( config => { const token = wx.getStorageSync('token'); // 获取本地存储中的 token if (token) { config.headers['Authorization'] = `${token}`; // 让每个请求携带自定义 token } return config; }, error => Promise.reject(error) ); export default service; ``` 上述代码片段展示了如何创建一个带有基础 URL 及超时时长设定的 Axios 实例,并通过拦截器机制自动附加鉴权头信息给每一个发出的请求[^2]。 #### 使用 Axios 进行 GET/POST 请求 接下来展示两个简单的例子说明怎样利用刚刚配置好的 Axios 实现 GET 和 POST 请求: ##### 执行 GET 请求 ```javascript async function fetchData() { try { let response = await http.get('/api/data'); console.log(response.data); } catch (error) { console.error(`Error fetching data: ${error.message}`); } } ``` ##### 提交表单数据 via POST ```javascript async function submitForm(formData) { try { let response = await http.post('/api/form', formData); console.log(response.data); } catch (error) { console.error(`Failed to post form data: ${error.message}`); } } ``` 以上就是关于在 UniApp微信小程序里使用 Axios 发起 HTTP 请求的方法介绍[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值