网络请求使用指南
本项目封装了基于 Promise 风格的网络请求库,支持拦截器、统一 Loading 处理等功能。
基础配置
网络请求的基础配置在 common/config.js
中定义:
javascript
// common/config.js
export const baseUrl = 'https://api.example.com' // 基础 URL
export const requestTimeout = 10000 // 请求超时时间(毫秒)
export const uploadTimeout = 30000 // 上传超时时间(毫秒)
请求封装
网络请求封装在 common/network/http.js
中,基于 uni-app 的 uni.request
API。
请求实例
项目导出了两个请求实例:
javascript
// common/network/http.js
export const http = new Request({ /* 配置 */ }) // 普通请求实例
export const uploadFile = new UploadFile({ /* 配置 */ }) // 文件上传实例
基本使用
GET 请求
javascript
import { http } from '@/common/network/http.js'
// 基本 GET 请求
const getUserInfo = async () => {
try {
const userInfo = await http.get('/api/user/info')
console.log('用户信息:', userInfo)
} catch (error) {
console.error('请求失败:', error)
}
}
// 带参数的 GET 请求
const getUserList = async (page, size) => {
try {
const params = { page, size }
const userList = await http.get('/api/user/list', params)
console.log('用户列表:', userList)
} catch (error) {
console.error('请求失败:', error)
}
}
POST 请求
javascript
// 基本 POST 请求
const createUser = async (userData) => {
try {
const result = await http.post('/api/user/create', userData)
console.log('创建成功:', result)
} catch (error) {
console.error('创建失败:', error)
}
}
// 带请求头的 POST 请求
const login = async (loginData) => {
try {
const headers = { 'Custom-Header': 'value' }
const result = await http.post('/api/auth/login', loginData, headers)
console.log('登录成功:', result)
} catch (error) {
console.error('登录失败:', error)
}
}
文件上传
javascript
import { uploadFile } from '@/common/network/http.js'
// 上传文件
const uploadAvatar = async (filePath) => {
try {
const result = await uploadFile.uploadFile(filePath)
console.log('上传成功:', result)
} catch (error) {
console.error('上传失败:', error)
}
}
拦截器
请求拦截器
请求拦截器在 common/network/http.js
中定义:
javascript
const requestInterceptor = async function(options) {
// 添加 token
options.header['token'] = uni.getStorageSync('token')
// 文件大小限制
if (options.filePath) fileLimit(options)
// 参数过滤
if (options.data) paramsFilter(options.data, options)
// 显示 loading
if (!excludeLoadingUrl.includes(options.url.replace(baseUrl, ''))) {
const { setLoading } = useGlobalStore()
setLoading(true)
requestLoadingCount++
}
}
响应拦截器
响应拦截器处理返回数据和错误:
javascript
const responseInterceptor = async function(res) {
const { reqConf, err } = res
// 隐藏 loading
if (!excludeLoadingUrl.includes(reqConf.url.replace(baseUrl, ''))) {
requestLoadingCount--
if (!requestLoadingCount) {
const { setLoading } = useGlobalStore()
setLoading(false)
}
}
if (res.statusCode == 200) {
// 处理成功响应
if (res.data.code == 200) {
dataFactory(res.data.data)
return res.data.data
} else {
// 处理业务错误
logReqErr(res)
uni.showToast({
icon: "none",
title: res.data.msg || res.data.message || `Error code ${res.data.code || 'none'}`,
duration: 2000,
})
return Promise.reject(res)
}
} else {
// 处理网络错误
logReqErr(res)
uni.showToast({
icon: "none",
title: "Server error",
duration: 2000,
})
return Promise.reject(res)
}
}
统一 Loading 处理
项目实现了统一的 Loading 处理机制:
javascript
// 在 global store 中管理 loading 状态
const excludeLoadingUrl = ['/api/xxx'] // 不显示 loading 的 url
let requestLoadingCount = 0
// 显示 loading
if (!excludeLoadingUrl.includes(options.url.replace(baseUrl, ''))) {
const { setLoading } = useGlobalStore()
setLoading(true)
requestLoadingCount++
}
// 隐藏 loading
if (!excludeLoadingUrl.includes(reqConf.url.replace(baseUrl, ''))) {
requestLoadingCount--
if (!requestLoadingCount) {
const { setLoading } = useGlobalStore()
setLoading(false)
}
}
错误处理
网络错误
网络错误会统一提示"Server error":
javascript
uni.showToast({
icon: "none",
title: "Server error",
duration: 2000,
})
业务错误
业务错误会显示后端返回的错误信息:
javascript
uni.showToast({
icon: "none",
title: res.data.msg || res.data.message || `Error code ${res.data.code || 'none'}`,
duration: 2000,
})
最佳实践
- 统一入口:所有网络请求都通过封装的 http 实例发起
- 错误处理:在业务代码中正确处理 Promise 的 reject 情况
- 参数校验:发送请求前对参数进行必要的校验
- Loading 控制:对于不需要显示 Loading 的接口,添加到 excludeLoadingUrl 数组中
- 请求日志:开发环境下会输出详细的请求日志,便于调试
通过合理使用网络请求封装,可以提升代码的可维护性和用户体验。