前言
今天写小程序,微信的原生的请求模块使用起来非常麻烦,所以就想着自己封装一个类似于axios的功能,本代码直接使用的es6规范,如果要适应浏览器,请自行转换
我先说一下执行流程
调用get或者post方法开始执行请求流程
-》 对传入的url和config和data等参数进行处理
-》 进入请求拦截器(Y)
-》 发起网络请求
-》进入响应拦截器 (Y)
-》 返回响应结果
就这么简单,这是我个人对axios的基本理解,如果有错误还请指正
代码
废话不多说,直接上代码
class Request {
//默认的配置项
config = {
baseUrl: "",
header: {},
}
//所有允许的返回状态码,不在其中的都会报错
statusCodes = /^2\d\d$/
constructor(config = {}) {
this.config = config
}
//外部设置BaseUrl,对其进行规范处理(结尾不带/)
set baseUrl(BaseUrl) {
BaseUrl = BaseUrl || BaseUrl + ''
if (/https?:\/\//.test(BaseUrl)) {
this.config.baseUrl = BaseUrl.endsWith("/") ? BaseUrl.slice(0, -1) : BaseUrl
}
this.config.baseUrl = BaseUrl || ""
}
//外部获取BaseUrl
get baseUrl() {
return this.config.baseUrl;
}
isFussCode(statusCode) {
return this.statusCodes.test(statusCode)
}
//格式化URL
FormatUrl(url) {
let isUrl = /https?:\/\//.test(url)
if (!isUrl) {
return url.startsWith("/") ? (this.baseUrl + url) : (this.baseUrl + "/" + url)
}
return url
}
//请求方法(私有,禁止外部调用此方法,因为此方法不会经过拦截器)
#req = (method, url, params, config) => {
const that = this;
return new Promise((resolve, reject) => {
//对应各种平台的原生网络模块即可适应各种平台
uni.request({
method,
url,
data: params,
header: config.header,
success: (res) => {
//判断状态码是非在允许范围内
if (that.isFussCode(res.statusCode)) {
resolve(res)
} else {
reject(new Error(`Request Waring: Response statusCodes: ${res.statusCode} is not in operation. You can provide statusCodes that modify the Request to define permissible statusCodes, such as /^2\\d\\d$/`))
}
},
fail: (err) => {
reject(err)
}
})
})
}
//下面是两个拦截器的默认值
/**
* 请求拦截器
* 接收4个参数:config, params, url, method
* 返回一个config作为新的config
* 如果要中断流程,返回一个reject或者抛出一个错误即可
* */
requestIntercept = function (config, params, url, method) {
return config
}
/**
* 响应拦截器
* 返回response
* 如果要中断流程,返回一个reject或者抛出一个错误即可
* */
responseIntercept = function (response) {
return response
}
//按流程请求,私有方法,为了防止外部修改,因为其他方法依赖此方法
#request = async (configs) => {
let {config, params, url, method} = configs
//请求拦截器,获取到新的config
config = await this.requestIntercept(config, params, url, method)
//请求发送
let response = await this.#req(method, url, params, config)
//响应拦截器
return await this.responseIntercept(response)
}
//合并Object,约往后级别越高
mergeObject(obj1, obj2) {
obj1 = JSON.parse(JSON.stringify(obj1))
for (const requestKey in obj2) {
if (obj1.hasOwnProperty(requestKey)) {//两个对象都含有该属性
if (typeof obj2[requestKey] === "object") {
obj1[requestKey] = fun01(obj1[requestKey], obj2[requestKey])
} else {
obj1[requestKey] = obj2[requestKey]
}
} else {
obj1[requestKey] = obj2[requestKey]
}
}
return obj1
}
//发送一个GET请求
async get(url, params, config) {
return await this.#request({
params,
url: this.FormatUrl(url),
config: this.mergeObject(this.config, config),
method: "GET"
})
}
//发送一个POST请求
async post(url, params, config) {
return await this.#request({
params,
url: this.FormatUrl(url),
config: this.mergeObject(this.config, config),
method: "POST"
})
}
}
export default Request
一个Api例子
import Request from "../Util/Request";
const request = new Request({
baseUrl: "http://127.0.0.1:10086/"
})
//...
export const getOpenId = params => request.post("https://www.baidu.com/", params)
//...
希望我的代码对你有一点帮助
最后,开来加入QQ群一起讨论技术吧,里面各种大牛等着你喔。我们非常乐意为萌新们解决问题,更加乐意与大神们讨论技术,一起成长。qq群: 365399843