实战篇:(五)UniApp 中 Request 封装与使用全解析(避坑指南)
我们可以根据请求方法类型,动态设置,使请求头适应不同接口的需求。// 根据请求类型动态设置 Content-Type?{ ["content-type"]: options.contentType } // 如果有传入 contentType 则使用: {};// 默认返回空对象} else {return {};避坑指南POST请求的通常是或,而GET请求不需要,根据接口文档调整传参格式。环境切
UniApp 中 Request 封装与使用全解析(避坑指南)
在 UniApp 项目中,接口请求是不可或缺的一部分。为了提高代码的可维护性和扩展性,合理封装请求至关重要。本文将介绍如何在 UniApp 项目中进行 request 请求的封装与使用,并给出避坑指南,帮助你在开发过程中少走弯路。
一、封装请求的基本思路
为了简化和统一接口调用,我们可以将请求逻辑封装到一个通用方法中。通过封装 request,可以为每次请求自动带上公共的请求头、处理全局错误和请求状态,减少重复代码。
1. 基础配置与环境切换
// 引入必要的工具和模块
import errorCode from "@/utils/errorCode"; // 错误码字典
import store from "@/store"; // 状态管理器,用于全局 loading 控制
import { globalData } from "@/globalData"; // 全局配置
import { md5DigestAsHex } from "@/utils/auth"; // MD5 加密工具
// 根据当前环境切换基础请求地址
let baseURL = globalData.baseUrl;
if (process.env.NODE_ENV === "development") {
baseURL = "/main"; // 开发环境使用本地代理
}
避坑指南:开发环境和生产环境需要不同的请求地址,避免在开发时直接请求生产接口,导致数据污染。
2. 自定义请求头设置
我们可以根据请求方法类型,动态设置 Content-Type,使请求头适应不同接口的需求。
// 根据请求类型动态设置 Content-Type
function getContentType(options) {
if (options.method?.toLocaleUpperCase() === "POST" || options.method?.toLocaleUpperCase() === "DELETE") {
return options.contentType
? { ["content-type"]: options.contentType } // 如果有传入 contentType 则使用
: {}; // 默认返回空对象
} else {
return {};
}
}
避坑指南:POST 请求的 Content-Type 通常是 application/json 或 application/x-www-form-urlencoded,而 GET 请求不需要 Content-Type,根据接口文档调整传参格式。
3. request 方法封装
request 方法是核心,它负责发起请求、设置请求头、处理请求的成功和失败。
// 全局请求封装,返回一个 Promise
export const request = (options) => {
return new Promise((resolve, reject) => {
store.commit("loading"); // 开启全局 loading 状态
// 特殊处理:如果是登录验证码接口,清除本地缓存的 token
if (options.url === "/login/captcha/captcha") {
uni.removeStorageSync("token");
}
uni.request({
url: baseURL + options.url, // 拼接基础地址和接口地址
method: options.method || "GET", // 默认请求方法为 GET
data: options.data || options.params || {}, // 传递的参数
dataType: options.dataType || "json", // 请求的数据类型,默认为 JSON
responseType: options.responseType || "text", // 响应的数据类型
header: {
devtype: "app", // 自定义请求头
rid: "tempTokenId-" + md5DigestAsHex(uni.getStorageSync("token")), // 加密 token
token: uni.getStorageSync("token"), // 从本地缓存中获取 token
...getContentType(options) // 动态获取 Content-Type
},
// 请求成功回调
success: (res) => {
const code = res.data.code || 200; // 服务器返回的状态码,默认为 200
const msg = errorCode[code] || res.data.msg || errorCode["default"]; // 错误信息提示
if (code == 401) {
// 处理未授权的情况,弹出提示框并跳转到登录页
uni.showModal({
title: "提示",
content: msg,
showCancel: false,
success: (res) => {
if (res.confirm) {
uni.reLaunch({ url: "/pages/login/index" });
}
}
});
} else if (code == 500) {
// 处理服务器错误
uni.showToast({
title: msg,
icon: "none",
mask: true,
duration: 2000
});
} else {
// 特殊处理:如果是登录接口,保存返回的 token
if (options.url === "/login/captcha/captcha") {
uni.setStorageSync("token", res.header.token);
}
// 根据响应类型返回数据
resolve(options.responseType === "arraybuffer" ? res : res.data);
}
},
// 请求失败回调
fail: (err) => {
console.log(baseURL + options.url, err); // 打印错误日志
reject(err); // 返回错误信息
},
// 请求完成后关闭 loading
complete() {
store.commit("loaded");
}
});
});
};
避坑指南:
- 在发起请求前,确保
token是最新的,否则会导致认证失败。可以在登录接口中更新token并存储在本地。 - 接口响应为
500错误时,除了简单的toast提示,还可以添加更细致的错误处理,比如重试机制。
二、模块化 API 管理
使用封装后的 request 方法,我们可以通过模块化的方式管理项目中的 API。以下是在 @/api/user.js 中封装的两个用户相关接口:
import { request } from "@/common/request.js";
// 获取公钥接口
export function getPublicKey(params) {
return request({
url: "/login/getPublicKey?_t=" + new Date().getTime(), // 动态添加时间戳,防止缓存
method: "get",
params
});
}
// 用户登录接口
export function doLogin(data, urlType, temporaryToken) {
return request({
url: "/login/dologin", // 登录接口
method: "post", // POST 请求
dataType: "json", // 请求的数据类型
data, // 传递的登录数据
temporaryToken
});
}
避坑指南:
- 动态添加时间戳
_t,可以防止 GET 请求被浏览器缓存,确保每次请求都能拉取最新数据。 - 在登录请求时,确保
data中传递的字段与后端接口一致,避免因参数格式不符而导致登录失败。
三、完整的 request.js 代码
为了便于参考,以下是完整的 request.js 代码:
import errorCode from "@/utils/errorCode";
import store from "@/store";
import { globalData } from "@/globalData";
import { md5DigestAsHex } from "@/utils/auth";
let baseURL = globalData.baseUrl;
if (process.env.NODE_ENV === "development") {
baseURL = "/main";
}
function getContentType(options) {
if (options.method?.toLocaleUpperCase() === "POST" || options.method?.toLocaleUpperCase() === "DELETE") {
return options.contentType
? { ["content-type"]: options.contentType }
: {};
} else {
return {};
}
}
export const request = (options) => {
return new Promise((resolve, reject) => {
store.commit("loading");
if (options.url === "/login/captcha/captcha") {
uni.removeStorageSync("token");
}
uni.request({
url: baseURL + options.url,
method: options.method || "GET",
data: options.data || options.params || {},
dataType: options.dataType || "json",
responseType: options.responseType || "text",
header: {
devtype: "wxapp",
rid: "tempTokenId-" + md5DigestAsHex(uni.getStorageSync("token")),
token: uni.getStorageSync("token"),
...getContentType(options)
},
success: (res) => {
const code = res.data.code || 200;
const msg = errorCode[code] || res.data.msg || errorCode["default"];
if (code == 401) {
uni.showModal({
title: "提示",
content: msg,
showCancel: false,
success: function (res) {
if (res.confirm) {
uni.reLaunch({ url: "/pages/login/index" });
}
}
});
} else if (code == 500) {
uni.showToast({
title: msg,
icon: "none",
mask: true,
duration: 2000
});
} else {
if (options.url === "/login/captcha
/captcha") {
uni.setStorageSync("token", res.header.token);
}
resolve(options.responseType === "arraybuffer" ? res : res.data);
}
},
fail: (err) => {
console.log(baseURL + options.url, err);
reject(err);
},
complete() {
store.commit("loaded");
}
});
});
};
四、总结与避坑要点
- 环境切换:确保开发和生产环境的接口地址正确配置,避免数据泄露或污染。
- 动态设置请求头:根据不同请求类型灵活调整
Content-Type,确保数据传输格式符合后端要求。 - 统一错误处理:将通用错误处理集中管理,确保用户能及时了解请求状态。
- Token 管理:定时清理过期
token并在请求时加密存储,避免认证问题。
通过以上封装,你的 UniApp 项目将变得更加灵活、稳定,同时也减少了重复代码。
上一篇
实战篇:(四)Vue2 + Three.js 创建可交互的360度全景视图,可控制旋转、缩放完整代码
下一篇
实战篇:(六)创建属于自己的 Vue 3 组件库:主题切换与样式管理
更多推荐


所有评论(0)