uniapp如何封装uni.request 全局使用
在 UniApp 中封装 uni.request
实现全局使用,可通过以下方案实现 统一配置、拦截器管理、错误处理和全局调用。以下是完整实现步骤:
一、基础封装方案(推荐)
1. 创建 http.js
请求封装模块
// utils/http.js// 基础配置
const BASE_URL = 'https://api.example.com'
const TIMEOUT = 15000// 请求队列(用于防止重复提交)
const pendingRequests = new Map()// 生成请求唯一标识
const generateReqKey = (config) => {return `${config.url}&${config.method}`
}// 核心请求函数
const request = (options) => {// 合并配置const config = {url: options.url,data: options.data || {},method: options.method || 'GET',header: {'Content-Type': 'application/json','X-Token': uni.getStorageSync('token') || '', // 自动携带token...(options.header || {}),},timeout: TIMEOUT,...options,}// 处理完整URLif (!config.url.startsWith('http')) {config.url = BASE_URL + config.url}// 防止重复请求拦截const reqKey = generateReqKey(config)if (pendingRequests.has(reqKey)) {return Promise.reject({ errMsg: '重复请求已取消' })}pendingRequests.set(reqKey, config)return new Promise((resolve, reject) => {uni.request({...config,success: (res) => {// 请求完成后移除队列pendingRequests.delete(reqKey)// 全局响应拦截器if (res.statusCode === 200) {// 业务状态码处理(示例)if (res.data.code === 401) {uni.navigateTo({ url: '/pages/login/login' })return reject(res.data)}resolve(res.data)} else {// HTTP状态码错误处理reject({ code: res.statusCode,message: `请求失败: ${res.errMsg}`})}},fail: (err) => {pendingRequests.delete(reqKey)// 网络错误统一处理reject({code: -1,message: '网络连接失败,请检查网络'})},complete: () => {// 可添加全局Loading关闭逻辑uni.hideLoading()}})})
}// 封装常用方法
const http = {get: (url, params = {}, options = {}) => {return request({url,data: params,method: 'GET',...options})},post: (url, data = {}, options = {}) => {return request({url,data,method: 'POST',...options})},put: (url, data = {}, options = {}) => {// 其他方法类似封装}
}export default http
2. 全局挂载(main.js)
// main.js
import Vue from 'vue'
import App from './App'
import http from '@/utils/http'// 挂载到Vue原型
Vue.prototype.$http = http// 挂载到全局uni对象
uni.$http = http// 如需使用this.$http调用
Vue.use({install(Vue) {Vue.config.globalProperties.$http = http}
})
3. 页面中使用
// 在.vue文件中
export default {methods: {async fetchData() {try {// GET请求const res1 = await this.$http.get('/user', { id: 123 })// POST请求const res2 = await uni.$http.post('/login', {username: 'admin',password: '123456'})} catch (err) {uni.showToast({ title: err.message, icon: 'none' })}}}
}
二、高级功能扩展
1. 添加拦截器系统
// 在http.js中添加
const interceptors = {request: [],response: []
}// 注册拦截器
http.addRequestInterceptor = (interceptor) => {interceptors.request.push(interceptor)
}http.addResponseInterceptor = (interceptor) => {interceptors.response.push(interceptor)
}// 修改request函数
const request = async (options) => {// ...原有代码...// 执行请求拦截器for (const interceptor of interceptors.request) {config = await interceptor(config) || config}return new Promise((resolve, reject) => {uni.request({...config,success: async (res) => {// 执行响应拦截器let response = resfor (const interceptor of interceptors.response) {response = await interceptor(response) || response}// ...后续处理...}})})
}
2. 使用示例(Token刷新)
// 在main.js中注册拦截器
http.addRequestInterceptor(config => {if (!config.url.includes('/refresh-token')) {const token = uni.getStorageSync('token')if (token) config.header['X-Token'] = token}return config
})http.addResponseInterceptor(async res => {if (res.data.code === 401) {// Token过期自动刷新const newToken = await http.post('/refresh-token', {refreshToken: uni.getStorageSync('refreshToken')})uni.setStorageSync('token', newToken)// 重新发送原请求return http(res.config)}return res
})
三、多端适配要点
H5跨域处理
// 开发环境代理配置 (vue.config.js) devServer: {proxy: {'/api': {target: 'https://api.example.com',changeOrigin: true,pathRewrite: { '^/api': '' }}} }
小程序域名白名单
需在
manifest.json
配置合法域名
"mp-weixin": {"appid": "xxx","setting": {"urlCheck": false},"permission": {"scope.userLocation": {"desc": "需要获取您的位置信息"}},"requiredPrivateInfos": ["getLocation"] }
App端证书校验
// 仅iOS需要处理 if (uni.getSystemInfoSync().platform === 'ios') {config.sslVerify = false // 关闭SSL验证(仅测试环境) }
四、最佳实践建议
全局Loading控制
// 请求计数 let requestCount = 0http.addRequestInterceptor(config => {if (!config.hideLoading) {requestCount === 0 && uni.showLoading({ title: '加载中', mask: true })requestCount++}return config })http.addResponseInterceptor(response => {if (!response.config.hideLoading) {requestCount--requestCount === 0 && uni.hideLoading()}return response })
请求重试机制
const retryRequest = (config, retry = 3) => {return request(config).catch(err => {return retry > 0 ? retryRequest(config, retry - 1) : Promise.reject(err)}) }
TypeScript支持
// http.d.ts declare module '@vue/runtime-core' {interface ComponentCustomProperties {$http: {get<T = any>(url: string, params?: object): Promise<T>;post<T = any>(url: string, data?: object): Promise<T>;}} }
封装优势:
统一管理所有网络请求逻辑
自动处理 token 和权限认证
支持多端差异化配置
提供拦截器实现业务解耦
内置防重复提交和错误重试机制