打造高效的 uni-app 网络请求流程:自定义 Request 请求库最佳实践
一. 前言
之前通过一篇文章的介绍,详细说明了在 uni-app 框架中,使用大约100 行代码 打造小而美的 uni-app 请求库,基于 uni.request
,支持多种运行环境,包括浏览器 H5、小程序、APP 等各端。
文章链接:100 行代码打造小而美的 uni-app 请求库(一)
因为我已经用 uni-http 开发了许多个成型的 APP、H5、 及小程序,Android 和 iOS 均已正常上线应用商店,因此可以证明,它的兼容性是良好的。
本篇文章我们继续聊聊 uni-http 这个请求框架,并主要实现以下功能:
-
支持处理请求的
loading
状态 -
支持
upload
文件上传
二. uni-http 是什么
uni-http 基于 uni.request
封装的一款小而美的请求工具库,它具有开箱即用,简洁高效的应用特点。uni-http 使用 TypeScript 开发, 支持 Vue2、Vue3 版本的 uni-app,支持 H5,APP,微信小程序等。
假设我们的文中使用的 http 是已经经过实例化后的实例:
const http = new Http();
// 设置统一的头部
const header = { "Content-Type": "application/json" };
// 仅为示例 API 域名,使用时替换自己的接口域名即可
const baseURL = "https://www.example.com";
// 设置 baseURL 和 header,支持链式调用
http.setBaseURL(baseURL).setHeader(header);
uni-http 最终实现的主要功能有以下几个重要点:
1. 提供统一的 Promise API
http
.request(url, params)
.then((res) => {
// 请求成功处理
})
.catch((err) => {
// 请求错误处理
});
2. 支持发起 GET
、POST
、PUT
、DELETE
请求
http.get(url, params, config);
http.post(url, params, config);
http.put(url, params, config);
http.delete(url, params, config);
3. 支持请求/响应拦截器
// 请求拦截器
http.interceptors.request.use(request, error);
// 响应拦截器
http.interceptors.response.use(request, error);
4. 支持链式调用
http.setBaseURL(baseURL).setHeader(header);
三. 支持处理请求的 loading
状态
前篇文章在说明请求 loading
状态的时候,并没有详细的说明,如何在请求的时候使用 loading
。
在使用 uni-http 请求的时候是可以声明是否配置 loading
参数的,比如:
// 用户登录接口
http.post("/api/login", { username, password }, { loading: true }).then((res) => {
// 处理 response 响应
if (res.status === 1) {
console.log(res);
}
});
以上的代码表示,用户在登录的时候,配置显示 loading
,那么我们可以在请求拦截器,响应拦截器中判断是否有配置 loading
,如果配置了 loading
,我们可以进行管理它。
// 设置请求拦截器
http.interceptors.request.use(
(request) => {
if (request.loading) {
// 如果配置了loading,请求开始需要显示,比如使用全局的loading模块加载
Tips.loading();
}
return request;
},
(error) => Promise.resolve(error)
);
// 设置响应拦截器
http.interceptors.response.use(
(response) => Promise.resolve(response),
(error) => Promise.reject(error),
(complete) => {
if (complete.request.loading) {
// 如果配置了loading,请求完成需要关闭
Tips.loaded();
}
}
);
比如,我在有题记软考小程序中,是这么使用的
-
封装一个全局的
loading
组件 -
使用 uni-http 控制请求接口时的
loading
显示和隐藏
如下图演示效果(文末已给出小程序链接):
四. 支持 upload 上传
前篇文章在写源码的时候并没有单独实现文件上传的功能,因为使用 post 的方式也可以实现文件上传,比如:
http.post("/api/upload", formdata, {
headers: {
"Content-Type": "multipart/form-data",
},
});
其实 uni.uploadFile
的实现方式也是如此,uni-app 的官网对它的定义解释如下:
将本地资源上传到开发者服务器,客户端发起一个 POST 请求,其中 content-type 为 multipart/form-data
如页面通过 uni.chooseImage
等接口获取到一个本地资源的临时文件路径后,可通过此接口将本地资源上传到指定服务器。
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
uni.uploadFile({
url: "https://www.example.com/api/upload",
filePath: tempFilePaths[0],
name: "file",
formData: {
user: "admin",
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
},
});
},
});
而接下来我们使用官方 uni.uploadFile
方法来实现文件上传,并将它封装到 uni-http 类库中去。
目标:基于
uni.uploadFile
,将 uni-http 添加upload
方法,支持上传文件。
想要实现以上这个目标,我们先来了解下 uni.uploadFile
,通过官方文档链接, uni.uploadFile
是将本地资源上传到开发者服务器,客户端发起一个 POST
请求,其中 content-type
为 multipart/form-data
。
那么,基于以上的了解,我们是否可以使用已有的 POST
请求来实现 uploadFile
呢?
// 如果是上传文件
if (options.method === "upload") {
url = url && url.indexOf("http") !== 0 ? options.baseURL + url : url;
return new Promise((resolve, reject) => {
uni.uploadFile({
url,
filePath: data.filePath,
name: data.name,
formData: data.formData || {},
success(res) {
resolve(res);
},
fail(e) {
reject(e);
},
});
});
}
有了以上代码的兼容,uni-http 也支持文件上传的 API,它主要是基于官方 uni.uploadFile
来实现的,因此使用方式和兼容性与官方一致。
接下来我们可以这样来使用文件上传了,这样做的好处是:使用 uploadFile API 可以沿用文章开始已经实例化的 uni-http 的公用配置:
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
http
.upload("/api/upload", {
filePath: tempFilePaths[0],
name: "file",
formData: {
user: "admin",
},
})
.then((res) => {
// 请求成功
});
},
});
五. 总结
本篇文章我们主要学习了 uni-http 的相关配置项:
-
uni-http 支持处理请求的
loading
状态,可以配置选项是否显示loading
,结合请求/响应拦截器进行业务处理显示隐藏状态,进而可以实现接口请求时配置是否显示loading
-
基于
uni.uploadFile
,在 uni-http 库中支持 upload 方式,当然,你也可以使用正常的 post 请求实现文件上传。