前言
微信小程序官方提供了 wx.request(OBJECT) 方法来实现网络请求。
小程序网络请求的缺点
小程序框架自带的网络请求和Ajax请求非常相似都是异步请求,请求参数中需要送入url、method、data、header等参数,还要设置success成功的回调函数和fail失败的回调函数,当无数个success的嵌套再嵌套,导致每一次看代码逻辑都要费劲千辛万苦。
这就是传说中的回调地狱,那有什么办法去解决呢?当然有,那就是Promise。
与微信原生请求库对比有哪些优点?
- api方法调用,你可以实现跟Axios一样的调用
- 默认和自定义的请求成功、失败和完成的回调处理
- 可设置请求失败自动重新请求的次数
- 可以防止重复提交网络请求
- 每个请求设定requestCode
- 设置接口鉴权和token刷新操作
api.js
我们将实例封装到api.js中,全局引入调用,跟app.js分开,互不干扰,相互独立
// 获取小程序全局配置(变量、函数等)
const app = getApp()
// 定义网络请求API地址
const baseURL = '这里为你的api地址'
// 封装网络请求开始
const http = ({url,data,method,...other} = {}) => {
// 添加请求加载等待
wx.showLoading({
title: '加载中...'
})
// Promise封装处理
return new Promise((resolve, reject) => {
wx.request({
// 请求地址拼接
url: baseURL+url,
data: data,
// 获取请求头配置
header: getHeader(),
method: method,
...other,
// 成功或失败处理
complete: (res) => {
// 关闭等待
wx.hideLoading()
// 进行状态码判断并处理
if(res.statusCode === 204){
resolve(res)
}else if (res.statusCode === 401) {
// 检测到状态码401,进行token刷新并重新请求等操作
refreshToken().then(()=>_refetch(url,data,method)).then(resolve)
}else if(res.data.code !== 200){
// 获取后台返回报错信息
let title = res.data.err_msg
// 调用全局toast方法
showToast(title)
}else if(res.data.code === 200){
resolve(res)
}else {
reject(res)
}
}
})
})
}
// 添加请求toast提示
const showToast = title =>{
wx.showToast({
title: title,
icon: 'none',
duration: 1500,
mask:true
});
}
// 进行url字符串拼接
const getUrl = url => {
if (url.indexOf('://') == -1) {
url = baseURL + url
}
return url
}
//获取用户userToken
function getHeader(){
// 判断登录token是否存在
if(wx.getStorageSync('userToken')){
// 获取token并设置请求头
var token = wx.getStorageSync('userToken')
let auth = {
'Authorization': token.token_type +" "+ token.access_token
}
return auth
}
}
// 重构请求方式
const _fetch = (content) => {
return http({
url:content.url,
data:content.data,
method:content.method
})
}
// 添加刷新之后的操作处理方法
const refreshToken = () => {
return new Promise((resolve, reject) => {
// 获取token
var token = wx.getStorageSync('userToken')
// 设置请求data
let params = {
refresh_token:token.refresh_token
}
// 进行token刷新请求
wx.request({
url: getUrl('/app/connect/refresh'),
data:params,
// 设置请求header 鉴权
header: {
'Authorization': token.token_type +" "+ token.access_token
},
method:'post',
// 请求响应处理
complete: (res) => {
if(res.data.code === 200 ){
// 全局存储token
app.globalData.usertToken = res.data.data
// Storage存储token
wx.setStorage({
key:"userToken",
data:res.data.data,
// 存储成功处理
success:function(){
resolve()
}
})
}
}
})
});
}
const _refetch = (url,data,method) => {
return http({
url:url,
data:data,
method:method
})
}
//除开上面的调用方式之外,你也可以使用下面的这些方法,只需要关注是否传入method
const _get = (url, params = {}) => {
return http({
url,
params
})
}
const _post = (url, params = {}) => {
return http({
url,
params,
method: 'post'
})
}
const _put = (url, params = {}) => {
return http({
url,
params,
method: 'put'
})
}
const _delete = (url, params = {}) =>{
return http({
url,
params,
method: 'delete'
})
}
module.exports = {
baseURL,
refreshToken,
_fetch,
_refetch,
_get,
_post,
_put,
_delete
}
调用方式
post
const api = require('../utils/api.js')
api._fetch({
url: '/list',
data:data,
method:'post'
}).then(function (res) {
console.info(res)
}).catch(function (error) {
console.log(error);
});
get
const api = require('../utils/api.js')
api._fetch({
url: '/list',
data:data,
}).then(function (res) {
console.info(res)
}).catch(function (error) {
console.log(error);
});
结语
封装一个好的功能集(全局方法库),能更好的保证代码的一致性和工作的高效。