更新记录
0.0.1(2024-03-19)
下载此版本
出生了
平台兼容性
App |
快应用 |
微信小程序 |
支付宝小程序 |
百度小程序 |
字节小程序 |
QQ小程序 |
app-vue |
× |
√ |
√ |
× |
× |
× |
钉钉小程序 |
快手小程序 |
飞书小程序 |
京东小程序 |
× |
× |
× |
× |
H5-Safari |
Android Browser |
微信浏览器(Android) |
QQ浏览器(Android) |
Chrome |
IE |
Edge |
Firefox |
PC-Safari |
× |
× |
× |
× |
× |
× |
× |
× |
× |
请求示例请下载插件
class Request {
// 设置全局默认配置
setConfig(customConfig) {
// 深度合并对象,否则会造成对象深层属性丢失
this.config = this.deepMerge(this.config, customConfig);
}
// 深度合并对象
deepMerge(target = {}, source = {}) {
target = deepClone(target);
if (typeof target !== 'object' || typeof source !== 'object') return false;
for (var prop in source) {
if (!source.hasOwnProperty(prop)) continue;
if (prop in target) {
if (typeof target[prop] !== 'object') {
target[prop] = source[prop];
} else {
if (typeof source[prop] !== 'object') {
target[prop] = source[prop];
} else {
if (target[prop].concat && source[prop].concat) {
target[prop] = target[prop].concat(source[prop]);
} else {
target[prop] = deepMerge(target[prop], source[prop]);
}
}
}
} else {
target[prop] = source[prop];
}
}
return target;
}
// 主要请求部分
request(options = {}) {
// 检查请求拦截
if (this.interceptor.request && typeof this.interceptor.request === 'function') {
let tmpConfig = {};
let interceptorRequest = this.interceptor.request(options);
if (interceptorRequest === false) {
// 返回一个处于pending状态中的Promise,来取消原promise,避免进入then()回调
return new Promise(() => {});
}
this.options = interceptorRequest;
}
options.dataType = options.dataType || this.config.dataType;
options.url = options.url || '';
options.params = options.params || {};
options.header = Object.assign({}, this.config.header, options.header);
options.method = options.method || this.config.method;
options.timeout = this.config.timeout || 60000;
return new Promise((resolve, reject) => {
options.complete = (response) => {
// 请求返回后,隐藏loading(如果请求返回快的话,可能会没有loading)
// #ifdef MP-ALIPAY
my.hideLoading();
// #endif
// #ifndef MP-ALIPAY
uni.hideLoading();
// #endif
// 清除定时器,如果请求回来了,就无需loading
clearTimeout(this.config.timer);
this.config.timer = null;
// 判断用户对拦截返回数据的要求,如果originalData为true,返回所有的数据(response)到拦截器,否则只返回response.data
if (this.config.originalData) {
// 判断是否存在拦截器
if (this.interceptor.response && typeof this.interceptor.response === 'function') {
let resInterceptors = this.interceptor.response(response);
// 如果拦截器不返回false,就将拦截器返回的内容给this.$u.post的then回调
if (resInterceptors !== false) {
resolve(resInterceptors);
} else {
// 如果拦截器返回false,意味着拦截器定义者认为返回有问题,直接接入catch回调
reject(response);
}
} else {
// 如果要求返回原始数据,就算没有拦截器,也返回最原始的数据
resolve(response);
}
} else {
if (response.statusCode == 200) {
if (this.interceptor.response && typeof this.interceptor.response ===
'function') {
let resInterceptors = this.interceptor.response(response.data);
if (resInterceptors !== false) {
resolve(resInterceptors);
} else {
reject(response.data);
}
} else {
// 如果不是返回原始数据(originalData=false),且没有拦截器的情况下,返回纯数据给then回调
resolve(response.data);
}
} else {//处理状态码不是200,可自定义处理
if((response.statusCode == null || response.statusCode == undefined || response.statusCode == '') && this.config.isNetworkTips){
// #ifdef MP-ALIPAY
my.showToast({
content: '请检查网络,或稍后再试!',
type: 'none',
duration: 2000,
mask:true
});
// #endif
// #ifndef MP-ALIPAY
uni.showToast({
title: '请检查网络,或稍后再试!',
icon: 'none',
duration: 2000,
mask:true
});
// #endif
resolve({code:10000});
return
}else{
resolve(response.data);
// let config = {};
// if(typeof response.data == 'string'){
// config = JSON.parse(response.data);
// return resolve(config);
// }else{
// return resolve(response.data);
// }
}
// 不返回原始数据的情况下,服务器状态码不为200,modal弹框提示
// if(response.errMsg) {
// uni.showModal({
// title: response.errMsg
// });
// }
// if(options.data.NoReminder == "禁止弹窗"){
// reject(response)
// return
// }
// if (response.errMsg) {
// // #ifdef MP-ALIPAY
// my.showToast({
// content: '请检查网络,或稍后再试!',
// type: 'none',
// duration: 2000,
// mask:true
// });
// // #endif
// // #ifndef MP-ALIPAY
// uni.showToast({
// title: '请检查网络,或稍后再试!',
// icon: 'none',
// duration: 2000,
// mask:true
// });
// // #endif
// resolve(response.data)
// }
// reject(response)
}
}
}
// 判断用户传递的URL是否/开头,如果不是,加上/,这里使用了uView的test.js验证库的url()方法
options.url = this.validateUrl(options.url) ? options.url : (this.config.baseUrl + (options.url
.indexOf('/') == 0 ?
options.url : '/' + options.url));
// 是否显示loading
// 加一个是否已有timer定时器的判断,否则有两个同时请求的时候,后者会清除前者的定时器id
// 而没有清除前者的定时器,导致前者超时,一直显示loading
if (this.config.showLoading && !this.config.timer) {
this.config.timer = setTimeout(() => {
// #ifdef MP-ALIPAY
my.showLoading({
content: this.config.loadingText,
mask: this.config.loadingMask
})
// #endif
// #ifndef MP-ALIPAY
uni.showLoading({
title: this.config.loadingText,
mask: this.config.loadingMask
})
// #endif
this.config.timer = null;
}, this.config.loadingTime);
}
uni.request(options);
})
// .catch(res => {
// // 如果返回reject(),不让其进入this.$u.post().then().catch()后面的catct()
// // 因为很多人都会忘了写后面的catch(),导致报错捕获不到catch
// return new Promise(()=>{});
// })
}
/**
* 验证URL格式
*/
validateUrl(value) {
return /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value)
}
constructor() {
/*
所有参数解释:
https://uniapp.dcloud.net.cn/api/request/request.html#request
*/
this.config = {//可以在这里配置信息,也可以在实例化之后配置,在最下面注释里面
baseUrl: 'http://localhost:5000', // 请求的根域名
// 默认的请求头
header: {
'Content-Type': 'application/json'
},
method: 'POST',
// 设置为json,返回后uni.request会对数据进行一次JSON.parse
dataType: 'json',
timeout: 1000 * 30,//超时时间,单位 ms
// #ifndef MP-ALIPAY
responseType: 'text',// 此参数无需处理,因为5+和支付宝小程序不支持,默认为text即可
// #endif
showLoading: true, // 是否显示请求中的loading
loadingText: '努力加载中~',
loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms
timer: null, // 定时器
originalData: false, // 是否在拦截器中返回服务端的原始数据,见文档说明
loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
isNetworkTips:true,//是否断网提示
}
// 拦截器
this.interceptor = {
// 请求前的拦截
request: (config) => {
let sn = '';
try {
const value = uni.getStorageSync('deviceId');
if (value) {
sn = value;
}
} catch (e) {
// error
}
config.data.sn = sn;
return config
},
// 请求后的拦截
response: (config) => {
return config;
}
}
// get请求
this.get = (url, data = {}, header = {}, loading = true,loadingText = '努力加载中~') => {
// throw Error 测试报错返回500
if (loading == false) {
this.config.showLoading = false;
} else {
this.config.loadingText = loadingText;
this.config.showLoading = true;
}
return this.request({
method: 'GET',
url,
header,
data
})
}
// post请求
this.post = (url, data = {}, header = {}, loading = true,loadingText = '努力加载中~') => {
if (loading == false) {
this.config.showLoading = false;
} else {
this.config.loadingText = loadingText;
this.config.showLoading = true;
}
return this.request({
url,
method: 'POST',
header,
data
})
},
// put请求
this.put = (url, data = {}, header = {}, loading = true,loadingText = '努力加载中~') => {
if (loading == false) {
this.config.showLoading = false;
} else {
this.config.loadingText = loadingText;
this.config.showLoading = true;
}
return this.request({
url,
method: 'PUT',
header,
data
})
}
}
}
/*
第301-322行代码可以在main里面实例化配置也可以
*/
const http = new Request;
// 请求拦截
http.interceptor.request = (config) => {
console.log('请求拦截')
return config;
}
// 响应拦截
http.interceptor.response = (res) => {
console.log('响应拦截')
return res;
}
/* 自定义配置,和this.config配置一样
// http.setConfig({
// baseUrl: 'https://api.example.com',
// loadingText: '努力加载中~',
// loadingTime: 800,
// })
*/
export default {
get:http.get,
post:http.post,
put:http.put,
};