uni-app 网络请求封装
章节介绍
网络请求是移动应用开发中的核心功能之一,几乎所有应用都需要与后端服务器进行数据交互。uni-app 提供了 uni.request API 用于发起网络请求,但在实际开发中,直接使用原生 API 会导致代码冗余、错误处理不一致等问题。本章节将详细介绍如何在 uni-app 中封装网络请求,包括请求拦截器、响应拦截器和错误处理等核心知识点,以及如何构建统一的网络请求模块,帮助你提升代码质量和开发效率。
核心知识点讲解
1. 网络请求基础
uni-app 提供了 uni.request API 用于发起网络请求,支持 GET、POST 等多种请求方式。
基本使用
uni.request({
url: 'https://api.example.com/login',
method: 'POST',
data: {
username: 'admin',
password: '123456'
},
header: {
'Content-Type': 'application/json'
},
success: (res) => {
console.log('请求成功:', res.data);
},
fail: (err) => {
console.error('请求失败:', err);
},
complete: () => {
console.log('请求完成');
}
});支持的配置项
url:请求地址method:请求方法(GET、POST、PUT、DELETE 等)data:请求数据header:请求头timeout:超时时间dataType:响应数据类型responseType:响应类型sslVerify:是否验证 SSL 证书success:请求成功回调fail:请求失败回调complete:请求完成回调
2. 网络请求封装
为了提高代码的可维护性和复用性,我们需要封装网络请求模块,统一处理请求配置、错误处理、拦截器等。
1. 创建基础请求模块
// utils/request.js
// 基础配置
const BASE_URL = 'https://api.example.com';
const TIMEOUT = 10000; // 10秒超时
/**
* 基础请求方法
* @param {Object} config - 请求配置
* @returns {Promise} - 返回Promise
*/
const request = (config) => {
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + config.url,
method: config.method || 'GET',
data: config.data || {},
header: {
'Content-Type': 'application/json',
...config.header
},
timeout: config.timeout || TIMEOUT,
success: (res) => {
resolve(res);
},
fail: (err) => {
reject(err);
}
});
});
};
export default request;2. 添加请求方法
// utils/request.js
// 基础配置
const BASE_URL = 'https://api.example.com';
const TIMEOUT = 10000; // 10秒超时
/**
* 基础请求方法
* @param {Object} config - 请求配置
* @returns {Promise} - 返回Promise
*/
const request = (config) => {
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + config.url,
method: config.method || 'GET',
data: config.data || {},
header: {
'Content-Type': 'application/json',
...config.header
},
timeout: config.timeout || TIMEOUT,
success: (res) => {
resolve(res);
},
fail: (err) => {
reject(err);
}
});
});
};
// 常用请求方法
export const get = (url, params = {}, config = {}) => {
return request({
url,
method: 'GET',
data: params,
...config
});
};
export const post = (url, data = {}, config = {}) => {
return request({
url,
method: 'POST',
data,
...config
});
};
export const put = (url, data = {}, config = {}) => {
return request({
url,
method: 'PUT',
data,
...config
});
};
export const del = (url, params = {}, config = {}) => {
return request({
url,
method: 'DELETE',
data: params,
...config
});
};
export default request;3. 添加拦截器
拦截器可以在请求发送前和响应返回后执行一些统一的逻辑,如添加 token、处理错误等。
// utils/request.js
// 基础配置
const BASE_URL = 'https://api.example.com';
const TIMEOUT = 10000; // 10秒超时
// 拦截器
const interceptors = {
// 请求拦截器
request: (config) => {
// 添加 token
const token = uni.getStorageSync('token');
if (token) {
config.header = {
...config.header,
'Authorization': 'Bearer ' + token
};
}
// 显示加载中
uni.showLoading({
title: '加载中...',
mask: true
});
return config;
},
// 响应拦截器
response: (response) => {
// 隐藏加载中
uni.hideLoading();
return response;
},
// 错误拦截器
error: (error) => {
// 隐藏加载中
uni.hideLoading();
return Promise.reject(error);
}
};
/**
* 基础请求方法
* @param {Object} config - 请求配置
* @returns {Promise} - 返回Promise
*/
const request = (config) => {
// 应用请求拦截器
config = interceptors.request(config);
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + config.url,
method: config.method || 'GET',
data: config.data || {},
header: {
'Content-Type': 'application/json',
...config.header
},
timeout: config.timeout || TIMEOUT,
success: (res) => {
// 应用响应拦截器
const response = interceptors.response(res);
resolve(response);
},
fail: (err) => {
// 应用错误拦截器
const error = interceptors.error(err);
reject(error);
}
});
});
};
// 常用请求方法
export const get = (url, params = {}, config = {}) => {
return request({
url,
method: 'GET',
data: params,
...config
});
};
export const post = (url, data = {}, config = {}) => {
return request({
url,
method: 'POST',
data,
...config
});
};
export const put = (url, data = {}, config = {}) => {
return request({
url,
method: 'PUT',
data,
...config
});
};
export const del = (url, params = {}, config = {}) => {
return request({
url,
method: 'DELETE',
data: params,
...config
});
};
export default request;3. 响应处理和错误处理
统一响应处理
// utils/request.js
// 基础配置
const BASE_URL = 'https://api.example.com';
const TIMEOUT = 10000; // 10秒超时
// 拦截器
const interceptors = {
// 请求拦截器
request: (config) => {
// 添加 token
const token = uni.getStorageSync('token');
if (token) {
config.header = {
...config.header,
'Authorization': 'Bearer ' + token
};
}
// 显示加载中
uni.showLoading({
title: '加载中...',
mask: true
});
return config;
},
// 响应拦截器
response: (response) => {
// 隐藏加载中
uni.hideLoading();
const res = response.data;
// 统一处理响应
if (res.code !== 200) {
// 显示错误信息
uni.showToast({
title: res.message || '请求失败',
icon: 'none'
});
// 处理特殊错误码
if (res.code === 401) {
// 未授权,跳转到登录页
uni.navigateTo({
url: '/pages/login/login'
});
}
return Promise.reject(res);
}
return res;
},
// 错误拦截器
error: (error) => {
// 隐藏加载中
uni.hideLoading();
// 统一处理错误
let errorMessage = '网络请求失败';
if (error.errMsg.includes('timeout')) {
errorMessage = '请求超时,请检查网络连接';
} else if (error.errMsg.includes('network')) {
errorMessage = '网络错误,请检查网络连接';
} else if (error.errMsg.includes('404')) {
errorMessage = '请求地址不存在';
}
// 显示错误信息
uni.showToast({
title: errorMessage,
icon: 'none'
});
return Promise.reject(error);
}
};
/**
* 基础请求方法
* @param {Object} config - 请求配置
* @returns {Promise} - 返回Promise
*/
const request = (config) => {
// 应用请求拦截器
config = interceptors.request(config);
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + config.url,
method: config.method || 'GET',
data: config.data || {},
header: {
'Content-Type': 'application/json',
...config.header
},
timeout: config.timeout || TIMEOUT,
success: (res) => {
try {
// 应用响应拦截器
const response = interceptors.response(res);
resolve(response);
} catch (error) {
reject(error);
}
},
fail: (err) => {
// 应用错误拦截器
const error = interceptors.error(err);
reject(error);
}
});
});
};
// 常用请求方法
export const get = (url, params = {}, config = {}) => {
return request({
url,
method: 'GET',
data: params,
...config
});
};
export const post = (url, data = {}, config = {}) => {
return request({
url,
method: 'POST',
data,
...config
});
};
export const put = (url, data = {}, config = {}) => {
return request({
url,
method: 'PUT',
data,
...config
});
};
export const del = (url, params = {}, config = {}) => {
return request({
url,
method: 'DELETE',
data: params,
...config
});
};
export default request;自定义错误处理
// utils/request.js
// 错误处理函数
export const handleError = (error) => {
let errorMessage = '未知错误';
if (error.code) {
// 后端返回的错误
errorMessage = error.message || '请求失败';
} else if (error.errMsg) {
// 网络错误
if (error.errMsg.includes('timeout')) {
errorMessage = '请求超时,请检查网络连接';
} else if (error.errMsg.includes('network')) {
errorMessage = '网络错误,请检查网络连接';
} else if (error.errMsg.includes('404')) {
errorMessage = '请求地址不存在';
}
}
return errorMessage;
};
// 使用
try {
const res = await get('/api/user/list');
console.log(res);
} catch (error) {
const errorMessage = handleError(error);
uni.showToast({
title: errorMessage,
icon: 'none'
});
}4. 环境配置
在实际开发中,我们通常需要区分开发环境、测试环境和生产环境,使用不同的 API 地址。
环境配置
// config/env.js
// 环境配置
const env = {
// 开发环境
development: {
baseUrl: 'https://dev-api.example.com'
},
// 测试环境
test: {
baseUrl: 'https://test-api.example.com'
},
// 生产环境
production: {
baseUrl: 'https://api.example.com'
}
};
// 获取当前环境
const getEnv = () => {
// #ifdef H5
return 'development';
// #endif
// #ifdef MP-WEIXIN
return 'production';
// #endif
// 默认环境
return 'development';
};
// 导出当前环境的配置
export default env[getEnv()];使用环境配置
// utils/request.js
import env from '../config/env';
// 基础配置
const BASE_URL = env.baseUrl;
const TIMEOUT = 10000; // 10秒超时
// 其他代码...5. API 模块化
为了更好地组织代码,我们可以将 API 按照功能模块进行拆分,每个模块对应一个文件。
创建 API 模块
// api/user.js
import { get, post, put, del } from '../utils/request';
// 用户相关 API
export const userApi = {
// 登录
login: (data) => {
return post('/login', data);
},
// 注册
register: (data) => {
return post('/register', data);
},
// 获取用户信息
getUserInfo: () => {
return get('/user/info');
},
// 更新用户信息
updateUserInfo: (data) => {
return put('/user/info', data);
},
// 退出登录
logout: () => {
return post('/logout');
}
};
export default userApi;// api/product.js
import { get, post, put, del } from '../utils/request';
// 产品相关 API
export const productApi = {
// 获取产品列表
getProductList: (params) => {
return get('/products', params);
},
// 获取产品详情
getProductDetail: (id) => {
return get(`/products/${id}`);
},
// 添加产品
addProduct: (data) => {
return post('/products', data);
},
// 更新产品
updateProduct: (id, data) => {
return put(`/products/${id}`, data);
},
// 删除产品
deleteProduct: (id) => {
return del(`/products/${id}`);
}
};
export default productApi;统一导出 API
// api/index.js
import userApi from './user';
import productApi from './product';
// 统一导出所有 API
export default {
user: userApi,
product: productApi
};使用 API 模块
// 导入 API
import api from '@/api';
// 登录
try {
const res = await api.user.login({
username: 'admin',
password: '123456'
});
console.log('登录成功:', res);
} catch (error) {
console.error('登录失败:', error);
}
// 获取产品列表
try {
const res = await api.product.getProductList({
page: 1,
pageSize: 10
});
console.log('产品列表:', res);
} catch (error) {
console.error('获取产品列表失败:', error);
}实用案例分析
案例:封装统一的网络请求模块
1. 创建完整的请求模块
// utils/request.js
import env from '../config/env';
// 基础配置
const BASE_URL = env.baseUrl;
const TIMEOUT = 10000; // 10秒超时
// 拦截器
const interceptors = {
// 请求拦截器
request: (config) => {
// 添加 token
const token = uni.getStorageSync('token');
if (token) {
config.header = {
...config.header,
'Authorization': 'Bearer ' + token
};
}
// 显示加载中
if (config.showLoading !== false) {
uni.showLoading({
title: config.loadingText || '加载中...',
mask: config.loadingMask !== false
});
}
return config;
},
// 响应拦截器
response: (response) => {
// 隐藏加载中
uni.hideLoading();
const res = response.data;
// 统一处理响应
if (res.code !== 200) {
// 显示错误信息
uni.showToast({
title: res.message || '请求失败',
icon: 'none'
});
// 处理特殊错误码
if (res.code === 401) {
// 未授权,跳转到登录页
uni.navigateTo({
url: '/pages/login/login'
});
}
return Promise.reject(res);
}
return res;
},
// 错误拦截器
error: (error) => {
// 隐藏加载中
uni.hideLoading();
// 统一处理错误
let errorMessage = '网络请求失败';
if (error.errMsg.includes('timeout')) {
errorMessage = '请求超时,请检查网络连接';
} else if (error.errMsg.includes('network')) {
errorMessage = '网络错误,请检查网络连接';
} else if (error.errMsg.includes('404')) {
errorMessage = '请求地址不存在';
}
// 显示错误信息
uni.showToast({
title: errorMessage,
icon: 'none'
});
return Promise.reject(error);
}
};
/**
* 基础请求方法
* @param {Object} config - 请求配置
* @returns {Promise} - 返回Promise
*/
const request = (config) => {
// 应用请求拦截器
config = interceptors.request(config);
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + config.url,
method: config.method || 'GET',
data: config.data || {},
header: {
'Content-Type': 'application/json',
...config.header
},
timeout: config.timeout || TIMEOUT,
success: (res) => {
try {
// 应用响应拦截器
const response = interceptors.response(res);
resolve(response);
} catch (error) {
reject(error);
}
},
fail: (err) => {
// 应用错误拦截器
const error = interceptors.error(err);
reject(error);
}
});
});
};
// 常用请求方法
export const get = (url, params = {}, config = {}) => {
return request({
url,
method: 'GET',
data: params,
...config
});
};
export const post = (url, data = {}, config = {}) => {
return request({
url,
method: 'POST',
data,
...config
});
};
export const put = (url, data = {}, config = {}) => {
return request({
url,
method: 'PUT',
data,
...config
});
};
export const del = (url, params = {}, config = {}) => {
return request({
url,
method: 'DELETE',
data: params,
...config
});
};
// 错误处理函数
export const handleError = (error) => {
let errorMessage = '未知错误';
if (error.code) {
// 后端返回的错误
errorMessage = error.message || '请求失败';
} else if (error.errMsg) {
// 网络错误
if (error.errMsg.includes('timeout')) {
errorMessage = '请求超时,请检查网络连接';
} else if (error.errMsg.includes('network')) {
errorMessage = '网络错误,请检查网络连接';
} else if (error.errMsg.includes('404')) {
errorMessage = '请求地址不存在';
}
}
return errorMessage;
};
export default request;2. 创建环境配置文件
// config/env.js
// 环境配置
const env = {
// 开发环境
development: {
baseUrl: 'https://dev-api.example.com'
},
// 测试环境
test: {
baseUrl: 'https://test-api.example.com'
},
// 生产环境
production: {
baseUrl: 'https://api.example.com'
}
};
// 获取当前环境
const getEnv = () => {
// #ifdef H5
return 'development';
// #endif
// #ifdef MP-WEIXIN
return 'production';
// #endif
// 默认环境
return 'development';
};
// 导出当前环境的配置
export default env[getEnv()];3. 创建 API 模块
// api/user.js
import { get, post, put, del } from '../utils/request';
// 用户相关 API
export const userApi = {
// 登录
login: (data) => {
return post('/login', data, {
showLoading: false
});
},
// 注册
register: (data) => {
return post('/register', data, {
showLoading: false
});
},
// 获取用户信息
getUserInfo: () => {
return get('/user/info');
},
// 更新用户信息
updateUserInfo: (data) => {
return put('/user/info', data, {
loadingText: '更新中...'
});
},
// 退出登录
logout: () => {
return post('/logout');
}
};
export default userApi;// api/product.js
import { get, post, put, del } from '../utils/request';
// 产品相关 API
export const productApi = {
// 获取产品列表
getProductList: (params) => {
return get('/products', params);
},
// 获取产品详情
getProductDetail: (id) => {
return get(`/products/${id}`);
},
// 添加产品
addProduct: (data) => {
return post('/products', data, {
loadingText: '添加中...'
});
},
// 更新产品
updateProduct: (id, data) => {
return put(`/products/${id}`, data, {
loadingText: '更新中...'
});
},
// 删除产品
deleteProduct: (id) => {
return del(`/products/${id}`, {}, {
loadingText: '删除中...'
});
}
};
export default productApi;// api/index.js
import userApi from './user';
import productApi from './product';
// 统一导出所有 API
export default {
user: userApi,
product: productApi
};4. 使用示例
<!-- pages/login/login.vue -->
<template>
<view class="container">
<view class="login-form">
<text class="title">登录</text>
<view class="form-item">
<input
type="text"
v-model="userInfo.username"
placeholder="请输入用户名"
class="input"
/>
</view>
<view class="form-item">
<input
type="password"
v-model="userInfo.password"
placeholder="请输入密码"
class="input"
/>
</view>
<text v-if="error" class="error-message">{{ error }}</text>
<button
@click="handleLogin"
:disabled="loading"
class="login-button"
>
{{ loading ? '登录中...' : '登录' }}
</button>
</view>
</view>
</template>
<script>
import api from '@/api';
export default {
data() {
return {
userInfo: {
username: '',
password: ''
},
loading: false,
error: ''
};
},
methods: {
async handleLogin() {
if (!this.userInfo.username || !this.userInfo.password) {
this.error = '请输入用户名和密码';
return;
}
this.loading = true;
this.error = '';
try {
const res = await api.user.login(this.userInfo);
// 存储 token
uni.setStorageSync('token', res.data.token);
// 跳转到首页
uni.switchTab({
url: '/pages/index/index'
});
} catch (error) {
this.error = error.message || '登录失败';
} finally {
this.loading = false;
}
}
}
};
</script>
<style scoped>
.container {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 40rpx;
background-color: #f5f5f5;
}
.login-form {
width: 100%;
max-width: 500rpx;
background-color: #fff;
padding: 60rpx;
border-radius: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin-bottom: 60rpx;
color: #333;
}
.form-item {
margin-bottom: 40rpx;
}
.input {
width: 100%;
height: 80rpx;
border: 2rpx solid #e0e0e0;
border-radius: 10rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
.error-message {
color: #ff4d4f;
font-size: 24rpx;
margin-bottom: 30rpx;
display: block;
}
.login-button {
width: 100%;
height: 80rpx;
background-color: #409eff;
color: #fff;
font-size: 28rpx;
font-weight: bold;
border-radius: 10rpx;
margin-top: 20rpx;
}
.login-button:disabled {
background-color: #c0c4cc;
}
</style><!-- pages/index/index.vue -->
<template>
<view class="container">
<view class="product-list">
<view
v-for="product in productList"
:key="product.id"
class="product-item"
@click="navigateToDetail(product.id)"
>
<image :src="product.image" class="product-image"></image>
<view class="product-info">
<text class="product-name">{{ product.name }}</text>
<text class="product-price">¥{{ product.price }}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import api from '@/api';
export default {
data() {
return {
productList: []
};
},
onLoad() {
this.getProductList();
},
methods: {
async getProductList() {
try {
const res = await api.product.getProductList({
page: 1,
pageSize: 10
});
this.productList = res.data.list;
} catch (error) {
console.error('获取产品列表失败:', error);
}
},
navigateToDetail(id) {
uni.navigateTo({
url: `/pages/detail/detail?id=${id}`
});
}
}
};
</script>
<style scoped>
.container {
flex: 1;
padding: 20rpx;
background-color: #f5f5f5;
}
.product-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.product-item {
display: flex;
padding: 20rpx;
background-color: #fff;
border-radius: 10rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.product-image {
width: 160rpx;
height: 160rpx;
border-radius: 10rpx;
margin-right: 20rpx;
}
.product-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.product-name {
font-size: 28rpx;
color: #333;
margin-bottom: 10rpx;
}
.product-price {
font-size: 32rpx;
color: #ff4d4f;
font-weight: bold;
}
</style>常见问题与解决方案
1. 请求超时
问题:网络请求经常超时,可能的原因包括网络连接不稳定、服务器响应慢等。
解决方案:
- 增加超时时间,根据实际情况调整
- 添加网络状态检测,在网络不好时提示用户
- 实现请求重试机制,在超时后自动重试
- 优化服务器性能,减少响应时间
2. 跨域问题
问题:在 H5 端开发时,可能会遇到跨域问题,导致请求失败。
解决方案:
- 后端配置 CORS(跨域资源共享)
- 使用代理服务器转发请求
- 在 uni-app 中配置 H5 端的代理
3. Token 过期
问题:用户登录后,Token 过期导致请求失败。
解决方案:
- 在请求拦截器中检查 Token 是否存在
- 在响应拦截器中处理 401 错误,跳转到登录页
- 实现 Token 刷新机制,在 Token 即将过期时自动刷新
4. 错误处理不一致
问题:不同地方的错误处理方式不一致,导致用户体验差。
解决方案:
- 封装统一的错误处理函数
- 在响应拦截器中统一处理错误
- 使用 try/catch 捕获异步错误
- 提供友好的错误提示
5. 重复请求
问题:用户快速点击按钮,导致重复发送相同的请求。
解决方案:
- 实现请求防抖,防止重复点击
- 在请求发送前禁用按钮
- 实现请求缓存,对于相同的请求直接返回缓存结果
- 使用请求队列,管理并发请求
代码优化建议
1. 优化请求配置
// 优化前:每次请求都需要配置
uni.request({
url: 'https://api.example.com/user/list',
method: 'GET',
header: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
success: (res) => {
console.log(res);
},
fail: (err) => {
console.error(err);
}
});
// 优化后:使用封装的请求方法
import api from '@/api';
try {
const res = await api.user.getUserList({ page: 1, pageSize: 10 });
console.log(res);
} catch (error) {
console.error(error);
}2. 优化错误处理
// 优化前:重复的错误处理代码
try {
const res = await uni.request({ url: '/api/user/list' });
if (res.statusCode !== 200) {
uni.showToast({ title: '请求失败', icon: 'none' });
return;
}
console.log(res.data);
} catch (error) {
uni.showToast({ title: '网络错误', icon: 'none' });
console.error(error);
}
// 优化后:使用统一的错误处理
import api from '@/api';
import { handleError } from '@/utils/request';
try {
const res = await api.user.getUserList({ page: 1, pageSize: 10 });
console.log(res);
} catch (error) {
const errorMessage = handleError(error);
uni.showToast({ title: errorMessage, icon: 'none' });
}3. 优化 API 管理
// 优化前:API 散落在各个组件中
// 组件 A
uni.request({ url: '/api/user/login' });
// 组件 B
uni.request({ url: '/api/user/info' });
// 优化后:集中管理 API
// api/user.js
export const userApi = {
login: (data) => post('/login', data),
getUserInfo: () => get('/user/info')
};
// 组件中使用
import api from '@/api';
api.user.login(data);
api.user.getUserInfo();4. 优化加载状态
// 优化前:手动管理加载状态
uni.showLoading({ title: '加载中...' });
try {
const res = await uni.request({ url: '/api/user/list' });
console.log(res);
} catch (error) {
console.error(error);
} finally {
uni.hideLoading();
}
// 优化后:使用拦截器自动管理
import api from '@/api';
// 拦截器会自动处理加载状态
const res = await api.user.getUserList({ page: 1, pageSize: 10 });
console.log(res);5. 优化环境配置
// 优化前:硬编码 API 地址
const url = 'https://api.example.com/login';
// 优化后:使用环境配置
import env from '@/config/env';
const url = env.baseUrl + '/login';章节总结
本章节详细介绍了 uni-app 中的网络请求封装方法,包括:
- 网络请求基础:介绍了 uni.request API 的基本使用方法和配置项
- 网络请求封装:创建了基础请求模块,添加了常用请求方法
- 拦截器:实现了请求拦截器、响应拦截器和错误拦截器
- 响应处理和错误处理:统一处理响应数据和错误
- 环境配置:区分开发环境、测试环境和生产环境
- API 模块化:按照功能模块组织 API 代码
- 实用案例:通过完整的示例展示了如何封装和使用网络请求
- 常见问题与解决方案:针对网络请求中的常见问题提供了解决方案
- 代码优化建议:提供了网络请求相关的代码优化建议
通过本章节的学习,你应该能够掌握 uni-app 中的网络请求封装方法,构建更可靠、更易维护的网络请求系统。在实际开发中,应根据项目的具体需求,灵活调整网络请求的封装方式,确保代码质量和用户体验。