开发过程中,总喜欢对一些公共的方法进行一些特定的封装,以达到自己想要的效果,同时也可以使得代码简介、可维护、可复用,所以在自己实现一个wx小程序的时候特意对请求方式进行了封装,写的不好请别介意😐,喜欢可以点赞收藏
1、本文采用的还是官方提供的uni.request方式,参考uni-app
参数名 | 类型 | 必填 | 默认值 | 说明 | 平台差异说明 |
---|---|---|---|---|---|
url | String | 是 | 开发者服务器接口地址 | ||
data | Object/String/ArrayBuffer | 否 | 请求的参数 | App 3.3.7 以下不支持 ArrayBuffer 类型 | |
header | Object | 否 | 设置请求的 header,header 中不能设置 Referer | App、H5端会自动带上cookie,且H5端不可手动修改 | |
method | String | 否 | GET | 有效值详见下方说明 | |
timeout | Number | 否 | 60000 | 超时时间,单位 ms | H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序 |
dataType | String | 否 | json | 如果设为 json,会对返回的数据进行一次 JSON.parse,非 json 不会进行 JSON.parse | |
responseType | String | 否 | text | 设置响应的数据类型。合法值:text、arraybuffer | 支付宝小程序不支持 |
sslVerify | Boolean | 否 | true | 验证 ssl 证书 | 仅App安卓端支持(HBuilderX 2.3.3+),不支持离线打包 |
withCredentials | Boolean | 否 | false | 跨域请求时是否携带凭证(cookies) | 仅H5支持(HBuilderX 2.6.15+) |
firstIpv4 | Boolean | 否 | false | DNS解析时优先使用ipv4 | 仅 App-Android 支持 (HBuilderX 2.8.0+) |
enableHttp2 | Boolean | 否 | false | 开启 http2 | 微信小程序 |
enableQuic | Boolean | 否 | false | 开启 quic | 微信小程序 |
enableCache | Boolean | 否 | false | 开启 cache | 微信小程序、抖音小程序 2.31.0+ |
enableHttpDNS | Boolean | 否 | false | 是否开启 HttpDNS 服务。如开启,需要同时填入 httpDNSServiceId 。 HttpDNS 用法详见 移动解析HttpDNS | 微信小程序 |
httpDNSServiceId | String | 否 | HttpDNS 服务商 Id。 HttpDNS 用法详见 移动解析HttpDNS | 微信小程序 | |
enableChunked | Boolean | 否 | false | 开启 transfer-encoding chunked | 微信小程序 |
forceCellularNetwork | Boolean | 否 | false | wifi下使用移动网络发送请求 | 微信小程序 |
enableCookie | Boolean | 否 | false | 开启后可在headers中编辑cookie | 支付宝小程序 10.2.33+ |
cloudCache | Object/Boolean | 否 | false | 是否开启云加速(详见云加速服务) | 百度小程序 3.310.11+ |
defer | Boolean | 否 | false | 控制当前请求是否延时至首屏内容渲染后发送 | 百度小程序 3.310.11+ |
success | Function | 否 | 收到开发者服务器成功返回的回调函数 | ||
fail | Function | 否 | 接口调用失败的回调函数 | ||
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
2、首先我们可以先声明一个request类,在类的构造函数(constructor)中构建所需要的方法,对一些请求状态拦截,这个时候就可以使用api中addInterceptor进行拦截设置
参数名 | 类型 | 必填 | 默认值 | 说明 | 平台差异说明 |
---|---|---|---|---|---|
invoke | Function | 否 | 拦截前触发 | ||
returnValue | Function | 否 | 方法调用后触发,处理返回值 | ||
success | Function | 否 | 成功回调拦截 | ||
fail | Function | 否 | 失败回调拦截 | ||
complete | Function | 否 | 完成回调拦截 |
代码部分
1、新建一个request.js文件
const baseURL = "https://example.com"
uni.addInterceptor('request', {
invoke(args) {
// request 触发前拼接 url
args.url = (args?.baseURL ? args?.baseURL : baseURL) + args.url;
const token = uni.getStorageSync('user_token');
if (token) {
args.header = {
...args.header,
'Content-Type': 'application/json;charset=UTF-8',
Authorization: `${token}`,
}
}
},
success(args) {
// 请求成功后,修改code值为1
// args.data.code = 200
},
fail(err) {
console.log('interceptor-fail', err)
},
complete(res) {
}
})
当对接口响应状态进行拦截的时候,我是放在了complete完成回调方法里面,这个里面可以获取同时获取到成功和失败的情况;所以要实现定义一个状态码提示
export const checkStatus = (status) => {
let errorMessage = '';
if (!status) return;
switch (status) {
case 401:
errorMessage = '认证失败!';
break;
case 403:
errorMessage = '请求被拒绝!';
break;
case 404:
errorMessage = '请求不存在!';
break;
case 405:
errorMessage = '请求方法不允许!';
break;
case 408:
errorMessage = '请求超时!';
break;
case 500:
errorMessage = '服务器错误!';
break;
case 501:
errorMessage = '网络未实现!';
break;
case 502:
errorMessage = '服务器无响应!';
break;
case 503:
errorMessage = '服务器错误!';
break;
case 504:
errorMessage = '网络超时!';
break;
default:
}
return errorMessage;
};
2、然后对接口的状态进行判断提醒
complete(res) {
if (res.statusCode == 401) {
uni.showToast({
title: '认证失败',
icon: 'none',
duration: 2500,
})
uni.setStorageSync('user_token', null);
uni.setStorageSync('user_info', null);
setTimeout(() => {
uni.reLaunch({
url: '/pages/login/login'
})
}, 500)
} else if (res.statusCode != 200) {
uni.showToast({
title: checkStatus(res.statusCode) || res.statusCode || '接口网络异常',
icon: 'none',
duration: 2500,
})
} else if (res.statusCode == 200) {
if (res.data.code != 200) {
if (res.data.code == 401) {
uni.showToast({
title: '认证失败',
icon: 'none',
duration: 2500,
})
uni.setStorageSync('user_token', null);
uni.setStorageSync('user_info', null);
setTimeout(() => {
uni.reLaunch({
url: '/pages/login/login'
})
}, 500)
} else if (checkStatus(res.data.code)) {
uni.showToast({
title: checkStatus(res.data.code) || '',
icon: 'none',
duration: 2500,
})
} else {
uni.showToast({
title: res.data.message || res.data.msg || '',
icon: 'none',
duration: 2500,
})
}
}
}
uni.hideLoading();
}
到这里简易的拦截就做好了,这个时候就需要添加请求的方法,
request(config) {
return new Promise((resolve, reject) => {
uni.request({
...config,
success: (res) => {
if (res.data.code == 200) {
resolve(res.data);
}
reject(res.data.code)
},
fail(err) {
reject(err)
}
})
})
}
3、在请求的时候我们可能会习惯性的对请求方式进行分类,比如get、post、put、delete等方式,然后在项目的api中进行不同请求类型的调用,所以需要增加一个公共方法,以便能够在引入的时候能够使用不同的请求类型
首先封装一个httpRequest类,在类中对类型进行不同方法的封装,比如get请求方式
import Request from './request.js'
class httpRequest {
constructor() {}
get(url, data, config) {
return this.request('GET', url, {
data
}, config);
}
}
export default new httpRequest();
然后对request方法进行导入之前封装的Request请求类
import Request from './request.js'
class httpRequest {
constructor() {}
get(url, data, config) {
return this.request('GET', url, {
data
}, config);
}
request(method, url, data, config) {
return new Promise((resolve, reject) => {
Request.request({ // 使用正确的 request 实例
method,
url,
...data,
...config
}).then((resp) => {
try {
resolve(resp);
} catch (err) {
reject(err || new Error('request error!'));
}
}).catch((e) => {
reject(e || new Error('request error!'));
});
})
}
}
export default new httpRequest();
这个时候就配好了一个get请求方式,同时可以拿真实的接口进行验证,同时接口的域名需要在微信小程序中进行域名白名单的配置,否则调用的时候会没有权限。
完整代码
request.js文件
import {
checkStatus
} from './checkStatus.js'
const baseURL = '' //基本URL地址
class Request {
constructor(options) {
uni.addInterceptor('request', {
invoke(args) {
// request 触发前拼接 url
args.url = (args?.baseURL ? args?.baseURL : baseURL) + args.url;
const token = uni.getStorageSync('user_token');
if (token) {
args.header = {
...args.header,
'Content-Type': 'application/json;charset=UTF-8',
Authorization: `${token}`,
}
}
},
success(args) {
// 请求成功后,修改code值为1
// args.data.code = 200
},
fail(err) {
console.log('interceptor-fail', err)
},
complete(res) {
if (res.statusCode == 401) {
uni.showToast({
title: '认证失败',
icon: 'none',
duration: 2500,
})
uni.setStorageSync('user_token', null);
uni.setStorageSync('user_info', null);
setTimeout(() => {
uni.reLaunch({
url: '/pages/login/login'
})
}, 500)
} else if (res.statusCode != 200) {
uni.showToast({
title: checkStatus(res.statusCode) || res.statusCode || '接口网络异常',
icon: 'none',
duration: 2500,
})
} else if (res.statusCode == 200) {
if (res.data.code != 200) {
if (res.data.code == 401) {
uni.showToast({
title: '认证失败',
icon: 'none',
duration: 2500,
})
uni.setStorageSync('user_token', null);
uni.setStorageSync('user_info', null);
setTimeout(() => {
uni.reLaunch({
url: '/pages/login/login'
})
}, 500)
} else if (checkStatus(res.data.code)) {
uni.showToast({
title: checkStatus(res.data.code) || '',
icon: 'none',
duration: 2500,
})
} else {
uni.showToast({
title: res.data.message || res.data.msg || '',
icon: 'none',
duration: 2500,
})
}
}
}
uni.hideLoading();
}
})
}
request(config) {
return new Promise((resolve, reject) => {
uni.request({
...config,
success: (res) => {
if (res.data.code == 200) {
resolve(res.data);
}
if (config.isThrowError) {
resolve(res.data);
}
reject(res.data.code)
},
fail(err) {
reject(err)
}
})
})
}
}
export default new Request();
httpRequest.js文件
import Request from './request.js'
class httpRequest {
constructor() {}
get(url, data, config) {
return this.request('GET', url, {
data
}, config);
}
post(url, data, config) {
return this.request('POST', url, {
data
}, config);
}
put(url, data, config) {
return this.request('PUT', url, {
data
}, config);
}
delete(url, data, config) {
return this.request('DELETE', url, {
data
}, config);
}
request(method, url, data, config) {
return new Promise((resolve, reject) => {
Request.request({ // 使用正确的 request 实例
method,
url,
...data,
...config
}).then((resp) => {
try {
resolve(resp);
} catch (err) {
reject(err || new Error('request error!'));
}
}).catch((e) => {
reject(e || new Error('request error!'));
});
})
}
}
export default new httpRequest();
checkStatus.js文件
export const checkStatus = (status) => {
let errorMessage = '';
if (!status) return;
switch (status) {
case 401:
errorMessage = '认证失败!';
break;
case 403:
errorMessage = '请求被拒绝!';
break;
case 404:
errorMessage = '请求不存在!';
break;
case 405:
errorMessage = '请求方法不允许!';
break;
case 408:
errorMessage = '请求超时!';
break;
case 500:
errorMessage = '服务器错误!';
break;
case 501:
errorMessage = '网络未实现!';
break;
case 502:
errorMessage = '服务器无响应!';
break;
case 503:
errorMessage = '服务器错误!';
break;
case 504:
errorMessage = '网络超时!';
break;
default:
}
return errorMessage;
};