在 UniApp 项目开发中,经常需要与后端 API 进行数据交互。如果每个页面都直接使用 uni.request 发起请求,会导致代码冗余、难以维护。本文将深入探讨 UniApp 请求接口封装的最佳实践,帮助开发者告别重复劳动,提升开发效率,并在实际项目中更加高效地处理请求。
问题场景:未封装的请求方式的弊端
假设我们需要在多个页面获取用户信息,如果直接使用 uni.request,代码可能如下所示:
uni.request({
url: 'https://api.example.com/user/info',
method: 'GET',
success: (res) => {
if (res.statusCode === 200) {
this.userInfo = res.data;
} else {
uni.showToast({ title: '获取用户信息失败', icon: 'none' });
}
},
fail: (err) => {
uni.showToast({ title: '网络错误', icon: 'none' });
}
});
这种方式存在以下问题:
- 代码冗余: 相同的代码需要在多个页面重复编写。
- 难以维护: 如果 API 地址或请求头发生变化,需要修改所有使用
uni.request的地方。 - 错误处理分散: 每个请求都需要单独处理错误,增加了代码复杂度。
底层原理:Promise 封装与拦截器机制
为了解决上述问题,我们可以对 uni.request 进行 Promise 封装,并利用拦截器机制实现统一的请求处理。Promise 可以将异步请求转换为同步操作,方便链式调用和错误处理。拦截器则可以在请求发送前和响应返回后进行统一处理,例如添加请求头、处理错误状态码等。
Promise 封装
我们可以将 uni.request 封装成一个返回 Promise 对象的函数:
function request(options) {
return new Promise((resolve, reject) => {
uni.request({
...options,
success: (res) => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data);
} else {
reject(res);
}
},
fail: (err) => {
reject(err);
}
});
});
}
export default request;
拦截器机制
我们可以使用类似 Axios 的拦截器机制,在请求发送前和响应返回后进行统一处理。例如,可以在请求发送前添加 token,在响应返回后处理错误状态码。
代码解决方案:详细封装步骤
下面是一个完整的 UniApp 请求接口封装方案:
- 创建
request.js文件:
const baseURL = 'https://api.example.com'; // 基础URL
let pendingRequests = 0; // 并发请求计数器
function showLoading() {
if (pendingRequests === 0) {
uni.showLoading({
title: '加载中...'
});
}
pendingRequests++;
}
function hideLoading() {
pendingRequests--;
if (pendingRequests === 0) {
uni.hideLoading();
}
}
function request(options) {
return new Promise((resolve, reject) => {
// 请求拦截器
if (options.showLoading !== false) { // 可选参数,控制是否显示 loading
showLoading();
}
options.url = baseURL + options.url;
options.header = {
...options.header,
'Authorization': uni.getStorageSync('token') || '' // 从 Storage 中获取 token
};
uni.request({
...options,
success: (res) => {
// 响应拦截器
if (options.showLoading !== false) {
hideLoading();
}
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data);
} else if (res.statusCode === 401) {
// token 过期,重新登录
uni.navigateTo({
url: '/pages/login/login'
});
reject(res);
} else {
uni.showToast({
title: res.data.message || '请求失败',
icon: 'none'
});
reject(res);
}
},
fail: (err) => {
if (options.showLoading !== false) {
hideLoading();
}
uni.showToast({
title: '网络错误', icon: 'none'
});
reject(err);
}
});
});
}
// 封装 GET、POST、PUT、DELETE 方法
request.get = function(url, data, options = {}) {
options.method = 'GET';
options.url = url;
options.data = data;
return request(options);
};
request.post = function(url, data, options = {}) {
options.method = 'POST';
options.url = url;
options.data = data;
return request(options);
};
request.put = function(url, data, options = {}) {
options.method = 'PUT';
options.url = url;
options.data = data;
return request(options);
};
request.delete = function(url, data, options = {}) {
options.method = 'DELETE';
options.url = url;
options.data = data;
return request(options);
};
export default request;
- 在页面中使用:
import request from '@/utils/request.js';
export default {
data() {
return {
userInfo: {}
}
},
onLoad() {
this.getUserInfo();
},
methods: {
async getUserInfo() {
try {
const res = await request.get('/user/info');
this.userInfo = res;
} catch (err) {
console.error(err);
}
}
}
}
上述代码通过 import request from '@/utils/request.js'; 导入封装好的 request 对象,然后使用 request.get() 方法发起 GET 请求,获取用户信息。async/await 语法使异步代码更加简洁易懂。
实战避坑经验总结
- baseUrl 配置: 将 API 的基础 URL 放在
request.js文件中统一管理,方便修改。 - Token 管理: 将 Token 存储在 Storage 中,并在请求头中携带。 token的续签机制也很重要,可以设置过期时间,在拦截器中判断是否需要刷新token。可以考虑使用JWT(JSON Web Token)。
- 错误处理: 统一处理错误状态码,例如 401 状态码跳转到登录页面。
- Loading 提示: 在请求发送前显示 Loading 提示,请求完成后隐藏 Loading 提示,提升用户体验。可以使用节流或防抖来优化 loading 的显示,避免频繁闪烁。
- 并发控制: 限制并发请求数量,避免服务器压力过大。通过维护一个 pending 请求队列,超过最大并发数时,将请求放入队列中等待。
- Nginx 反向代理: 在生产环境中,通常会使用 Nginx 作为反向代理服务器,对 API 请求进行负载均衡和安全防护。 Nginx 可以配置 upstream 模块实现后端服务器的负载均衡,并设置缓存策略来提升性能。
- 宝塔面板: 可以使用宝塔面板快速搭建 Nginx 环境,简化配置过程。
- 并发连接数: 需要根据服务器的硬件配置和网络带宽,合理设置 Nginx 的并发连接数和 worker 进程数,避免服务器崩溃。
通过以上封装和优化,可以有效提高 UniApp 项目的开发效率和代码质量。记住,持续学习和实践是成为优秀架构师的关键。希望本文对你的项目有所帮助。
冠军资讯
键盘上的咸鱼