通常我们使用 axios 库中的 API 设置常用配置以及请求方法封装。更多详情,请查看:axios 常用配置以及请求方法封装。小程序中使用 wx.request API 进行网络请求数据,但是小程序中未对请求提供拦截 API。在 Taro 框架中,我们可以看的 Taro.addInterceptor(callback) API 可以使用拦截器在请求发出前或发出后做一些额外操作。这里的提供的拦截器:请求拦截和响应拦截是没有区分的。
wx.request 参数说明:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
url | string | 是 | 开发者服务器接口地址 | ||
data | string/object/ArrayBuffer | 否 | 请求的参数 | ||
header | Object | 否 | 设置请求的 header,header 中不能设置 Referer。content-type 默认为 application/json |
||
timeout | number | 否 | 超时时间,单位为毫秒 | 2.10.0 | |
method | string | GET | 否 | HTTP 请求方法 | |
dataType | string | json | 否 | 返回的数据格式 | |
responseType | string | text | 否 | 响应的数据类型 | 1.7.0 |
enableHttp2 | boolean | false | 否 | 开启 http2 | 2.10.4 |
enableQuic | boolean | false | 否 | 开启 quic | 2.10.4 |
enableCache | boolean | false | 否 | 开启 cache | 2.10.4 |
success | function | 否 | 接口调用成功的回调函数 | ||
fail | function | 否 | 接口调用失败的回调函数 | ||
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.method 的合法值:OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT。
通常我们的接口请求主要为 POST 和 GET 请求两种方式。更多详情参数,请查看:Taro 官网之 Taro.request API。
url 为必传参数,data、method、header 为非必传参数。
class HTTP {
request({
url,
data = {},
method = 'GET',
header = {'content-type': 'application/json'}
}) {
return new Promise((resolve, reject) => {
this._request(url, resolve, reject, data, method, header)
}).catch((reject) => {
console.log('catch', reject)
})
}
}
export { HTTP }
之所以要封装一下 wx.request API 的缘由:首先我们请求时,有些接口需要在请求前添加 loading 样式,待到请求结果响应时,将 loading 样式隐藏,同时接口中可能需要添加请求头之类的。
class HTTP {
// data 默认空, method 默认为 GET
_request(url, resolve, reject, data = {}, method = 'GET', header = {'content-type': 'application/json'}) {
let headerParam = {
Authorization: wx.getStorageSync("tokenInfo").token
};
this._show()
Taro.request({
url,
method,
data,
header: {
...header,
...headerParam,
},
success: (res) => {
wx.hideLoading()
if (res.statusCode == 200) {
resolve(res.data)
} else {
reject()
}
},
fail: (err) => {
wx.showToast({
title: '服务器网络错误!',
icon: 'loading',
duration: 1500
})
reject()
}
})
}
_show(){
wx.showLoading({
title: '加载中',
})
}
}
export { HTTP }
在接口定义文档中,我们只需采用 class 的 extends 继承封装的请求方法。
// src/servers/servers.js
import { HTTP } from '../utils/http.js'
const API = {
login: "login/decodeUserInfo", // 登录
......
}
class MineModel extends HTTP {
// 登陆
getLogin(encryptedData, iv, code){
return this.request({
url: API.login,
data: {
encryptedData,
iv,
code,
},
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
})
}
}
export { MineModel }
如何在页面中使用呢?
import { MineModel } from '../../models/mine.js'
const mineModel = new MineModel()
// 请求第三方接口
mineModel.getLogin(res.encryptedData, res.iv, code).then(res => {
console.log('请求第三方接口', res)
})
在调用 Taro.request 发起请求之前,调用 Taro.addInterceptor 方法为请求添加拦截器,拦截器的调用顺序遵循洋葱模型。
拦截器是一个函数,接受 chain 对象作为参数。chain 对象中含有 requestParmas 属性,代表请求参数。拦截器内最后需要调用 chain.proceed(requestParams) 以调用下一个拦截器或发起请求。
// src/servers/interceptors.js
import { getNewToken } from "./servers";
const customInterceptor = (chain) => {
const requestParams = chain.requestParams;
return chain.proceed(requestParams).then((res) => {
console.log(`http <-- ${url} result:`, res)
return res
// 对返回的信息做处理
})
};
比如 token 过期、请求服务器异常等问题。
Taro 提供了两个内置拦截器 logInterceptor 与 timeoutInterceptor,分别用于打印请求的相关信息和在请求超时时抛出错误。
Taro.addInterceptor(Taro.interceptors.logInterceptor)
Taro.addInterceptor(Taro.interceptors.timeoutInterceptor)
Taro.request({ url })
当然我们可以将拦截器放在一个数组中,代码如下:
const interceptors = [customInterceptor, Taro.interceptors.logInterceptor];
export default interceptors;
在加载请求方式中,采用 forEach 对拦截器中的每一项进行循环添加。