3.微信小程序 网络请求封装 (小程序基础库 从 2.10.2 开始 ,异步API 支持callback & Promise 两种调用方式)
当接口参数 Object对象中不包含success/fail/complete时,将默认返回promise,否则仍然按回调方式执行,无返回值。
但部分接口如,downloadFile, request, uploadFile等本身就有返回值,因此不支持promise调用方式,它们需要 promisify需要开发者自行封装 ,可参考Axios 封装
方式一:自定义封装
//-- 1、 请求文件 request.js
/***
* 封装类似 axios 调用请求方法
* 功能:
* 1.可实例化默认配置,带请求拦截和响应拦截, 可配置基础路径(可抽离切换不同环境域名)+ 接口路径
* 2. 带默认loading效果(可配置不展示)
* 3.带简单请求api:get/post/put/delete
* 4.可拦截token ,token不存在或失效可跳转登录页面
* 5. 支持上传方法
*
*/
class WxRequest {
// 默认请求参数
defaults = {
baseUrl: "", // 请求基准地址
url: "", // 开发者服务器接口地址
data: null, // 请求参数
method: "GET", // 默认请求方法
// 请求头
header: {
"Content-type": "application/json" // 设置数据交互格式
},
timeout: 60000, // 小程序默认请求超时 默认1分钟
isLoading: true // 是否使用默认loading , true使用 false 不使用
}
// 定义拦截器对象 包含请求拦截 和响应拦截
interceptors = {
// 请求拦截 在发出请求前 对参数进行新增和修改
request: (config) => config,
// 响应拦截 在服务器响应数据后 进行逻辑处理
response: (response) => response
}
// 定义数组队列,用来存储请求队列、存储请求标识
queue = []
// 用于创建和初始化类的属性和方法
// 在实例化时 传递的参数会被 constructor 形参接收
constructor(params = {}) {
// 通过 Object.assign() 方法合并参数
// 需要传入的参数覆盖默认参数,因此传入的参数放到最后
this.defaults = Object.assign({}, this.defaults, params)
}
// 发起请求 属性值和wx.request 保持一致
// 实例方法接收一个对象类型参数
request(options) {
//如果有新的请求,就清除上一次的定时器
this.timerId && clearTimeout(this.timerId)
//注意:需要先合并完整的请求地址(baseUrl + url)
options.url = this.defaults.baseUrl + options.url
// 合并调用时请求的参数
options = {
...this.defaults,
...options
}
// 在发送之前 调用请求拦截器
options = this.interceptors.request(options)
if (options.isLoading && options.method !== "UPLOAD") {
// 判断queue队列是否为空,若是空就展示loading; 若是不为空就不调用 wx.showLoading
this.queue.length === 0 && wx.showLoading()
// 往队列里添加 自定义请求标识
this.queue.push("request")
}
// 返回一个promise
return new Promise((reslove, reject) => {
// 是否时上传方法
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 })
reslove(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: (res) => {
// 不管成功还是失败 都需要调用响应拦截
// 在给响应拦截器传参时,需要把请求参数一起传递过去,方便调试排查
// 传递参数前,进行参数合并
// 不管时请求成功还是失败,都将数据传递给了拦截器
// 追加1个属性 isSuccess ,值为true 执行success ,值为false 执行fail
const mergeRes = Object.assign({}, res, {
config: options,
isSuccess: true
})
reslove(this.interceptors.response(mergeRes))
},
fail: (err) => {
// 不管成功还是失败 都需要调用响应拦截
const mergeErr = Object.assign({}, err, {
config: options,
isSuccess: false
})
reject(this.interceptors.response(mergeErr))
},
// 不管成功或失败都会执行
complete: () => {
if (options.isLoading) {
// 在每次请求后都会走complete 回调函数
// 每次 从 queue队列清除一个请求标志
this.queue.pop()
// 解决两个请求有依赖关系时,loading闪烁问题(解决方法:利用延迟回调)
this.queue.length === 0 && this.queue.push("request")
this.timerId = setTimeout(() => {
this.queue.pop()
// 删除标志后 判断队列是否为 空 ,若为空 说明并发多次请求都完成了,就需要隐藏loading
this.queue.length === 0 && wx.hideLoading()
}, 1)
}
}
})
}
})
}
//-----------封装快捷操作方法
// 封装 GET 实例方法
get(url, data = {}, config = {}) {
// 返回 基于 request 方法 封装的参数合并 请求
return this.request(Object.assign({
url,
data,
method: "GET"
}, config))
}
// 封装 DELETE 实例方法
delete(url, data = {}, config = {}) {
// 返回 基于 request 方法 封装的参数合并 请求
return this.request(Object.assign({
url,
data,
method: "DELETE"
}, config))
}
// 封装 POST 实例方法
post(url, data = {}, config = {}) {
// 返回 基于 request 方法 封装的参数合并 请求
return this.request(Object.assign({
url,
data,
method: "POST"
}, config))
}
// 封装 PUT 实例方法
put(url, data = {}, config = {}) {
// 返回 基于 request 方法 封装的参数合并 请求
return this.request(Object.assign({
url,
data,
method: "PUT"
}, config))
}
// 处理并发请求
all(...promise) {
// 通过展开运算符得到传入参数数组
return Promise.all(promise)
}
/**
* 上传方法
* @param {*} url 开发者服务器地址
* @param {*} filePath 要上传文件资源的路径 (本地路径)
* @param {*} name 文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容
* @param {*} config 其他配置
*/
upload(url, filePath, name="file", config = {}){
return this.request(Object.assign({url,filePath, name, method:"UPLOAD" },config))
}
}
export default WxRequest