前言
在项目开发过程中,往往需要对请求进行二次封装,这篇文章将对uni.request()进行二次封装,并实现多个环境的请求配置,对请求方式,数据格式等进行封装,将请求做到最简化。
一.封装uni.request()
第一步基于uni.request()进行二次封装,集成项目开发中需要的参数及方法。
新建src/request/index.ts文件内容如下:
/**
* 创建request请求
* @returns
*/
const request = <T = any>(
url: string, //接口地址
type: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT', //请求方式
data: AnyObject, //请求的参数
header: any //设置请求的 header
): Promise<T> => {
// 拼接url config.base后面会讲到
let apiUrl = config.base + url
// 这里是获取存在Store中的token,获取方式根据自身项目来
const userStore = useUserStore()
// 全局添加请求头
let obj = {
// 获取Store中的token || 获取本地存储的token
'Authori-zation': (userStore.token || storage.getData("TOKEN") || ""),
}
if (header) {
// 有无传入header,有则合并
let headers = Object.assign(header, obj);
header = headers;
} else {
header = obj
}
if (data) {
// 清除无用参数
Object.keys(data).forEach(key => {
if (data[key] == null || data[key] == undefined || data[key] === '') {
delete (data[key]);
}
})
}
return new Promise((resolve, reject) => {
uni.request({
url: apiUrl,
method: type,
data,
header,
success(res) {
if (res.statusCode == 200) {
const data: any = res.data;
if (data.code == 0) {
// 正常抛出数据
resolve(data.data as T)
} else {
if(data.code == 401) {
// 未登录
uni.redirectTo({
url: "" //未登录跳转指定页面
})
uni.hideLoading();
return reject(data);
}
// 错误数据
uni.hideLoading();
// 弹窗错误框,这里是自己封装组件,
common.toastErr(data.message || "网络请求异常")
reject(data);
}
} else {
console.log(data)
uni.hideLoading();
common.toastErr("网络请求异常")
reject(data)
}
},
fail(err) {
console.log(err)
uni.hideLoading();
common.toastErr("网络请求异常")
reject(err)
}
})
})
}
二.根据环境配置请求地址
上面我们已经对uni.request()进行了封装,前面代码中提到的config.base就是我们需要获取的地址,在项目开发过程中,往往会有多个环境,如开发环境、预生产环境、生产环境等等,那我们怎么根据不同环境来配置对应的请求地址或其他信息呢?
要做到根据不同环境读取不同配置信息,那我们这里就需要用到uni.getAccountInfoSync()方法,该方法可以获取当前小程序账号信息,其返回值miniProgram属性的envVersion值,就是我们想获取的当前小程序环境:
属性 | 类型 | 说明 |
envVersion | string | 小程序当前环境版本:develop开发板;trial体验版;release正式版 |
已经解决了获取环境问题,那我们就可以来配置不同环境啦,这里分三种环境:
- dev 开发环境
- test 测试环境
- prod 生产环境
在src下新建config文件,其下dev,test,prod三个文件夹用来配置对应信息。
先对配置进行ts规范,因为项目中可能不知请求地址一个配置,可能还有应用地图的key等其他信息,我们可以统一配置,新建config/types.ts 如下:
export interface IConfig {
// 接口主地址
base: string;
// 环境模式
mode: string;
// 地图key
mapKey: string;
// 密钥
secretKey: string;
}
接下来就是具体内容的配置,新建config/dev/index.ts如下:
// dev 开发环境
import {IConfig} from "../types";
const test: IConfig = {
// #ifdef H5
base: "",
// #endif
// #ifdef MP-WEIXIN
base:'http://192.168.1.15:8090/api',
// #endif
// 模式
mode: "dev",
// 地图key
mapKey: "",
// Secret Key
secretKey: ""
}
export default test;
新建config/test/index.ts如下:
// test 测试环境
import {IConfig} from "../types";
const test: IConfig = {
// #ifdef H5
base: "",
// #endif
// #ifdef MP-WEIXIN
base:'http://192.168.1.15:8090/api',
// #endif
// 模式
mode: "test",
// 地图key
mapKey: "",
// Secret Key
secretKey: ""
}
export default test;
新建config/prod/index.ts如下:
// prod 生产环境
import {IConfig} from "../types";
const test: IConfig = {
// #ifdef H5
base: "",
// #endif
// #ifdef MP-WEIXIN
base:'http://www.baidu.com/api',
// #endif
// 模式
mode: "prod",
// 地图key
mapKey: "",
// Secret Key
secretKey: ""
}
export default test;
上面三个文件中使用了#ifdef #endif 注释,这是因为我们的项目可能不只是在小程序上运行,如我开发过的项目就有一个溯原H5页面,那这时候就得区分不同平台,这里简单介绍一下如何区分:
#ifdef #endif其实就是条件编译,条件编译是用特殊注释作为标记,在编译时根据特殊注释,将注释里面的代码编译到不同平台,其写法如下:
已 #ifdef 或 #ifndef 加 %PLATFORM% 开头 ,中间部分写代码,以 #endif 结尾。
- #ifdef :if defined 仅在某平台存在
- #ifndef:if not defined 除了某平台均存在
- %PLATFORM%:平台名称,如H5,MP-WEIXIN
所以上面三个文件中条件编译的意思就是只在微信小程序存在/只在H5页面存在。
此时我们已经准备好了三种环境下的配置,那么接下来就是对当前环境的判断及使用,在config下新建index.ts 内容如下:
import { IConfig } from "./types";
import prod from "./prod";
import test from "./test";
import dev from "./dev";
let obj: IConfig;
// #ifdef MP-WEIXIN
const plat = uni.getAccountInfoSync().miniProgram.envVersion
if(plat === "release") {
obj = prod
} else if(plat === "trial") {
obj = test
} else {
obj = dev
}
// #endif
// #ifdef H5
if(import.meta.env.MODE === "production") {
obj = prod
} else if(import.meta.env.MODE === "test") {
obj = test
} else {
obj = dev
}
// #endif
export default obj;
这一文件中就用到了上面讲的获取当前环境的方法,来配置对应信息,前面在request/index文件中提到的config.base就是来自于此。
三.封装请求方式
到这个位置其实我们的封装已经可以使用了,但是在实际开发中,还分有get,post,put,delete等请求方式,及json,form表单等数据格式,那为了后续开发的便捷,我们还有继续根据请求方式及数据格式封装请求,这一部分就继续写在request/index.ts 文件中:
/**
* http get 请求
* @param url 请求接口
* @param data 请求参数
* @returns
*/
const get = <T = any>(
url: string,
data: AnyObject
): Promise<T> => {
return request(url, 'GET', data, {})
}
/**
* http post json请求
* @param url 请求接口
* @param data 请求参数
* @returns
*/
const postJ = <T = any>(
url: string,
data: AnyObject
): Promise<T> => {
return request(url, 'POST', data, {
'Content-Type': 'application/json'
})
}
/**
* http post form表单请求
* @param url 请求接口
* @param data 请求参数
* @returns
*/
const postW = <T = any>(
url: string,
data: AnyObject
): Promise<T> => {
return request(url, 'POST', data, {
'Content-Type': 'application/x-www-form-urlencoded'
})
}
/**
* http put json请求
* @param url 请求接口
* @param data 请求参数
* @returns
*/
const putJ = <T = any>(url: string, data: AnyObject): Promise<T> => {
return request(url, 'PUT', data, {
'Content-Type': 'application/json'
})
}
/**
* http put form表单请求
* @param url 请求接口
* @param data 请求参数
* @returns
*/
const putW = <T = any>(url: string, data: AnyObject): Promise<T> => {
return request(url, 'PUT', data, {
'Content-Type': 'application/x-www-form-urlencoded'
})
}
/**
* http delete请求
* @param url 请求接口
* @param data 请求参数
* @returns
*/
const del = <T = any>(url: string, data: AnyObject): Promise<T> => {
return request(url, 'DELETE', data, {})
}
export default {
get,
postJ,
postW,
putJ,
putW,
del
}
四.调用请求
接下来我们就根据上面封装的请求来试一试效果吧,新建src/apis文件:文章来源:https://www.toymoban.com/news/detail-487199.html
//引入封装方法
import http from "@/request";
export const getTest = () => http.get<any>(`url`, {})
export const postTest = (data:any) => http.postJ<any>(`url`, data)
总结
可以看到,封装之后的请求已经非常精简,配置好各个环境地址,根据请求方式,数据格式,选择对应的封装方法即可。文章来源地址https://www.toymoban.com/news/detail-487199.html
到了这里,关于【uniapp&微信小程序】封装uni.request()的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!