213 lines
6.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

class WxRequest {
// 定义实例属性,用来设置默认请求参数
defaults = {
baseURL: '', // 请求基准地址
url: '', // 接口的请求路径
data: null, // 请求参数
method: 'GET', // 默认的请求方法
// 请求头
header: {
'Content-type': 'application/json' // 设置数据的交互格式
},
timeout: 60000, // 默认的超时时长,小程序默认的超时时长是 1 分钟
isLoading: true // 控制是否使用默认的 loading默认值是 true 表示使用默认的 loading
}
// 定义拦截器对象
interceptors = {
// 请求拦截器
request: (config) => config,
// 响应拦截器
response: (response) => response
}
// 定义数组队列,用来存储请求队列、存储请求标识
queue = []
// constructor 用于创建和初始化类的属性以及方法
constructor(params = {}) {
// 注意:需要传入的参数,覆盖默认的参数,因此传入的参数需要放到最后
this.defaults = Object.assign({}, this.defaults, params)
}
/**
* @description request 实例方法发送网络请求,接收一个对象类型的参数
* @param {*} options 属性值和 wx.request() 方法调用时传递的参数保持一致
* @returns Promise
*/
request(options) {
// 如果有新的请求,就清除上一次的定时器
this.timerId && clearTimeout(this.timerId)
// 合并完整的请求地址
options.url = this.defaults.baseURL + options.url
// 合并请求参数:调用实例方法时传入的覆盖默认的以及实例配置的
options = { ...this.defaults, ...options }
// 控制 loading 的显示与隐藏
if (options.isLoading && options.method !== 'UPLOAD') {
this.queue.length === 0 && wx.showLoading()
this.queue.push('request')
}
// 在请求发送之前,调用请求拦截器,新增和修改请求参数
// 请求拦截器内部,会将新增和修改以后的参数返回
options = this.interceptors.request(options)
// 需要使用 Promise 封装 wx.request处理异步请求
return new Promise((resolve, reject) => {
// 如果 method 等于 UPLOAD 说明需要调用 wx.uploadFile() 方法
// 否则调用的是 wx.request() 方法
if (options.method === 'UPLOAD') {
wx.uploadFile({
...options,
success: (res) => {
// 需要将服务器返回的 JSON 字符串 通过 JSON.parse 转成对象
res.data = JSON.parse(res.data)
// 合并参数
const mergeRes = Object.assign({}, res, {
config: options,
isSuccess: true
})
resolve(this.interceptors.response(mergeRes))
},
fail: (err) => {
// 合并参数
const mergeErr = Object.assign({}, err, {
config: options,
isSuccess: false
})
reject(this.interceptors.response(mergeErr))
}
})
} else {
wx.request({
...options,
// 当接口调用成功时会触发 success 回调函数
success: (res) => {
// 合并请求参数,方便进行代码调试
// 追加 isSuccess 属性,是为了标识响应拦截器是 success 调用还是 fail 调用
const mergeRes = Object.assign({}, res, {
config: options,
isSuccess: true
})
resolve(this.interceptors.response(mergeRes))
},
// 当接口调用失败时会触发 fail 回调函数
fail: (err) => {
// 合并请求参数,方便进行代码调试
// 追加 isSuccess 属性,是为了标识响应拦截器是 success 调用还是 fail 调用
const mergeErr = Object.assign({}, err, {
config: options,
isSuccess: false
})
reject(this.interceptors.response(mergeErr))
},
// 接口调用结束的回调函数(调用成功、失败都会执行)
complete: () => {
// 如果需要显示 loading ,那么就需要控制 loading 的隐藏
if (options.isLoading) {
// 在每一个请求结束以后,都会执行 complete 回调函数
// 每次从 queue 队列中删除一个标识
this.queue.pop()
// 解决并发请求loading 闪烁问题
this.queue.length === 0 && this.queue.push('request')
//解决并发请求loading 闪烁问题
this.timerId = setTimeout(() => {
this.queue.pop()
this.queue.length === 0 && wx.hideLoading()
clearTimeout(this.timerId)
}, 1)
}
}
})
}
})
}
/**
* @description 封装 GET 实例方法
* @param {*} url 请求地址
* @param {*} data 请求参数
* @param {*} config 其他请求配置项
* @returns Promise
*/
get(url, data = {}, config = {}) {
// 需要调用 request 请求方法发送请求,只需要组织好参数,传递给 request 请求方法即可
// 当调用 get 方法时,需要将 request 方法的返回值 return 出去
return this.request(Object.assign({ url, data, method: 'GET' }, config))
}
/**
* @description 封装 DELETE 实例方法
* @param {*} url 请求地址
* @param {*} data 请求参数
* @param {*} config 其他请求配置项
* @returns Promise
*/
delete(url, data = {}, config = {}) {
return this.request(Object.assign({ url, data, method: 'DELETE' }, config))
}
/**
* @description 封装 POST 实例方法
* @param {*} url 请求地址
* @param {*} data 请求参数
* @param {*} config 其他请求配置项
* @returns Promise
*/
post(url, data = {}, config = {}) {
return this.request(Object.assign({ url, data, method: 'POST' }, config))
}
/**
* @description 封封装 PUT 实例方法
* @param {*} url 请求地址
* @param {*} data 请求参数
* @param {*} config 其他请求配置项
* @returns Promise
*/
put(url, data = {}, config = {}) {
return this.request(Object.assign({ url, data, method: 'PUT' }, config))
}
/**
* @description 处理并发请求
* @param {...promise} promise 传入的每一项需要是 Promise
* @returns Promise
*/
all(...promise) {
// 那么展开运算符会将传入的参数转成数组
return Promise.all(promise)
}
/**
* @description upload 实例方法,用来对 wx.uploadFile 进行封装
* @param {*} url 文件的上传地址、接口地址
* @param {*} filePath 要上传的文件资源路径
* @param {*} name 文件对应的 key
* @param {*} config 其他配置项
*/
upload(url, filePath, name = 'file', config = {}) {
return this.request(
Object.assign({ url, filePath, name, method: 'UPLOAD' }, config)
)
}
}
export default WxRequest