@10yun/cv-js-utils
Version:
常用 js-utils 工具类库
636 lines (620 loc) • 18.5 kB
JavaScript
import AxiosClassBase from 'axios';
// 添加加载状态标识
var loadingWin = false;
/**
* 是否在数组里
* @param key
* @param array
* @param regular
* @return {Boolean|*}
*/
function urlInArray(key, array, regular = false) {
if (regular) {
return !!array.find((item) => {
if (item && item.indexOf('*')) {
const rege = new RegExp('^' + item.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&').replace(/\*/g, '.*') + '$', 'g');
if (rege.test(key)) {
return true;
}
}
return item == key;
});
} else {
return array.includes(key);
}
}
/*
* 收集错误信息
*/
const EnumStatusToTitle = {
400: '请求错误',
400: '无效请求',
401: '未经授权',
403: '拒绝访问',
404: '请求出错',
408: '请求超时',
422: '请求参数错误',
500: '服务器错误',
501: '服务未实现',
502: '网络错误',
503: '服务不可用',
504: '网络超时',
505: 'HTTP版本不受支持',
10001: '未登录',
10002: 'token过期',
10009: '退出登录'
};
const EnumStatusToMsg = {
401: '没有权限,请重新登录'
};
class RequestClass {
constructor(options = {}) {
this.flagMap = options.flagMap || {};
this.flagAuth = options.flagAuth || {};
this.flagFunc = options.flagFunc;
this.baseURL = options.baseURL || '';
this.requests = Object.assign({}, options.requests || {});
this.headers = Object.assign({}, {}, options.headers || {});
// 需要加密的url
this.encryptURL = options.encryptURL || [];
this.encryptFlag = false;
this.canshuOpt = {};
this.retries = 3;
this.debugState = options.debug || false;
this.requestHandle = null;
/* 新创建 axios 实例配置 */
this.creSett = Object.assign(
{},
{
timeout: options.timeout || 5000, // request timeout
// 表示跨域请求时是否需要使用凭证;
// 开启withCredentials后,服务器才能拿到你的cookie
// 当然后端服务器也要设置允许你获取你开启了才有用
// withCredentials: true, // 开启跨域身份凭证
retry: 2
},
{}
);
this._initReqHandle();
}
debugLog() {
if (this.debugState) {
console.log('[调试]', ...arguments);
}
}
/* 初始化 request 句柄 */
_initReqHandle() {
/* 新创建 axios 实例配置 */
this.requestHandle = AxiosClassBase.create({
timeout: 10000, // request timeout
// 表示跨域请求时是否需要使用凭证;
// 开启withCredentials后,服务器才能拿到你的cookie
// 当然后端服务器也要设置允许你获取你开启了才有用
// withCredentials: true, // 开启跨域身份凭证
retry: 2,
...this.creSett,
baseURL: this.baseURL,
headers: {
...this.headers
// 'currPage':location.pathname,
// 'syOpenAppCsrfToken': '',
// 'syOpenAppSessionId': Lockr.get("sessionId"),
// 'X-Requested-With': 'XMLHttpRequest',
// 'Access-Control-Allow-Origin': '*',
// 'Content-Type': 'application/x-www-form-urlencoded',
// "Content-Type": "application/json; charset=UTF-8"
// get: {
// 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
// // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来
// },
// post: {
// 'Content-Type': 'application/json;charset=utf-8'
// // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来
// }
},
requests: {
...this.requests
}
// transformRequest: [(data) => {
// data = JSON.stringify(data)
// return data
// }],
// validateStatus() {
// // 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常
// return true
// },
// transformResponse: [(data) => {
// if (typeof data === 'string' && data.startsWith('{')) {
// data = JSON.parse(data)
// }
// return data
// }]
});
// requestHandle.defaults.withCredentials = true;
// 设置全局的请求次数,请求的间隙,用于自动再次请求
this.requestHandle.defaults.retry = 2;
this.requestHandle.defaults.retryDelay = 1000;
/**
* 请求拦截器:request拦截器==>对请求参数做处理
*/
this.requestHandle.interceptors.request.use(
(config) => {
// 修改请求状态
// loadingWin = true;
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
// const token = store.state.token;
// token && (config.headers.Authorization = token);
// let token = StorageObj.localGet('token');
// if (token) config.headers.Authorization = token;
return config;
},
(error) => {
this.debugLog('netRequestError ', error);
return this.netResponseError(error);
}
);
/**
* 响应拦截器:respone拦截器==>对响应做处理
*/
this.requestHandle.interceptors.response.use(
(response) => {
return this.netResponseOK(response);
},
(error) => {
return this.netResponseError(error);
}
);
}
/**
* 设置API
*/
setApiFlag(options) {
this.flagMap = options || {};
return this;
}
appendApiFlag(options) {
this.flagMap = Object.assign({}, this.flagMap, options || {});
return this;
}
setApiAuth(options) {
this.flagAuth = options || {};
return this;
}
appendApiAuth(options) {
this.flagAuth = Object.assign({}, this.flagAuth, options || {});
return this;
}
/**
* 设置header参数
* @param {Object} options
* @return {Class} this
*/
setDefHeaders(options) {
this.headers = Object.assign({}, this.headers, options || {});
this.requestHandle.defaults.headers = this.headers;
return this;
}
setHeaders(options) {
this.headers = Object.assign({}, this.headers, options || {});
return this;
}
/**
* 设置requests参数
* @param {Object} options
* @return {Class} this
*/
setDefRequests(options) {
this.requests = Object.assign({}, this.requests, options || {});
this.requestHandle.defaults.requests = this.requests;
return this;
}
setRequests(options) {
this.requests = Object.assign({}, this.requests, options || {});
return this;
}
/**
* 设置body 参数
* 设置 额外参数
* @param {Object} options
* @return {Class} this
*/
setOptions(options = {}) {
this.canshuOpt = Object.assign({}, this.canshuOpt, options || {});
return this;
}
/**
* 设置 signal
*/
setSignal(signal) {}
/**
* 请求前置
* 请求后置
*/
requestBefore(callFunc) {
this.requestBeforeCall = callFunc;
}
requestAfter(callFunc) {
this.requestAfterCall = callFunc;
}
/**
* 加密
*/
encrypt() {
this.encryptFlag = true;
return this;
}
__encryp_parse(url) {
let encryptFlag = false;
if (this.encryptURL && urlInArray(url, this.encryptURL, true)) {
encryptFlag = true;
}
if (this.encryptFlag) {
encryptFlag = true;
}
if (encryptFlag) {
// 是 Windows Xp, Vista, 7, 8 系统,不支持加密
const userAgent = window.navigator.userAgent;
if (
/Windows NT 5.1|Windows XP/.test(userAgent) ||
userAgent.indexOf('Windows NT 6.0') !== -1 ||
userAgent.indexOf('Windows NT 6.1') !== -1 ||
userAgent.indexOf('Windows NT 6.2') !== -1
) {
encryptFlag = false;
}
}
return encryptFlag;
}
/**
* 请求成功
*/
netResponseOK(response) {
this.debugLog('netResponseOK ', response);
// 请求异常
const responseStatus = response.status;
if (responseStatus !== 200) {
this.resetNetError({ type: 'error', message: '请求异常' });
return Promise.reject(error);
}
return this.resetNetResponse(response.data);
// return response;
}
/**
* 请求失败
*/
netResponseError(error) {
this.debugLog('netResponseError ', error);
const errMsg = (error && error.message) || '';
const responseStatus = (error && error.response && error.response.status) || 0;
const responseMsg = (error && error.response && (error.response.data.message || error.response.statusText)) || '';
// 服务器异常,请联系管理员
let lastTitle = '提示';
let lastMsg = '请求异常,请检查网络或联系管理员';
if (EnumStatusToTitle[responseStatus]) {
// 状态码 - 匹配 - 标题
lastTitle = EnumStatusToTitle[responseStatus];
}
if (EnumStatusToMsg[responseStatus]) {
// 状态码 - 匹配 - 信息
lastMsg = EnumStatusToMsg[responseStatus];
} else {
// 错误状态码 - 无匹配
if (errMsg.includes('Network Error')) {
lastMsg = '网络异常';
} else if (errMsg.includes('Not Found')) {
lastMsg = '未找到该请求';
} else if (errMsg.includes('timeout')) {
lastMsg = '请求超时,请刷新重试';
}
}
this.resetNetError({
title: lastTitle,
status: responseStatus,
type: 'error',
message: responseMsg || lastMsg,
error: errMsg
});
// 错误抛到业务代码
return Promise.reject(error);
// return new Promise((resolve, reject) => {
// this.resetNetError({ type: 'error', message: lastMsg, status: responseStatus, error: errMsg });
// return reject({ error });
// });
}
/***
* ================== ================== ================== ==================
* 允许重写
* ================== ================== ================== ==================
*/
/**
* 设置flag
*/
resetFlagConfig() {
return {
flag: {},
auth: {}
};
}
/**
* 设置错误时响应
*/
resetNetError(error) {
console.log(error.message || '');
}
/**
* 设置网络请求响应
* 设置自定义业务响应
*/
resetNetResponse(apiResData) {
// 修改请求状态
// loadingWin = false;
let apiResStatus = apiResData.status || apiResData.code || -1;
let apiResMessage = apiResData.msg || apiResData.message || '操作失败';
apiResStatus = parseInt(apiResStatus);
// 这里根据后端提供的数据进行对应的处理
switch (apiResStatus) {
// 没有凭证,请登录
case 100101:
// 【退出登录操作】
this.resetNetError({ type: 'error', message: apiResMessage });
break;
// 无效凭证,请重新登录
case 100102:
// 【退出登录操作】
let errorData = Object.assign(apiResData, { type: 'error', message: apiResMessage });
this.resetNetError(errorData);
break;
// 凭证过期,请重新登录
case 100103:
// 【退出登录操作】
window.location.href = '/';
break;
// syOpenAppToken 错误
case 100109:
break;
case 404:
case 100404:
let msg404 = apiResData.msg || '操作失败';
this.resetNetError({ type: 'error', message: `${msg404}` });
return Promise.reject(apiResData);
break;
// 处理成功
case 200:
// this.requestAfterCall?.();
return apiResData;
return Promise.resolve(apiResData);
break;
// 调试
case -1:
return Promise.reject({ message: 'error' });
break;
default:
return apiResData;
break;
}
}
/**
* 调用 API 统一 请求 方法
*
* @author ctocode-zhw
* @version 2018-12-20
* @param apiUrl 不需要域名,域名统一拼接,只填写相关请求接口 【必须】
* @param reqData 提交参数
* @return
*
*/
apiAll(type, apiUrl, reqData) {
if (apiUrl.includes('http://') || apiUrl.includes('https://')) {
// request_url = apiUrl
}
/**
* TODO 过滤除了 https:// 和 http:// 以外的 // 和 ///,但保留 ? 后面的内容
* request_url = request_url.replace(/^(https?:\/\/[^/]+)\/+/g, '$1/');
*/
/**
* 使用正则表达式进行过滤
* 过滤除了 https:// 和 http:// 以外的 // 和 ///
*/
apiUrl = apiUrl.replace(/([^:]\/)\/+/g, '$1');
this.requestHandle.defaults.headers = this.headers;
this.requestHandle.defaults.requests = this.requests;
let canshuOpt = this.canshuOpt || {};
this.canshuOpt = {};
/**
* 判断是否加密
*/
let encryptFlag = this.__encryp_parse(apiUrl);
/**
* 最后 type
*/
let last_type = this.__parse_method_type(type);
if (last_type == 'POST') {
return this.requestHandle.post(apiUrl, reqData, {
...canshuOpt
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
// 'Accept': 'application/json, text/javascript, */*; q=0.01',
// }
});
} else if (last_type == 'GET') {
return this.requestHandle.get(apiUrl, {
...canshuOpt,
params: {
...reqData
}
});
} else if (last_type == 'PUT') {
return this.requestHandle.put(apiUrl, {
...reqData
});
} else if (last_type == 'PATCH') {
return this.requestHandle.patch(apiUrl, {
...reqData
});
} else if (last_type == 'DELETE') {
return this.requestHandle.delete(apiUrl, {
data: {
...reqData
}
});
} else if (last_type == 'UPLOAD') {
return this.requestHandle.post(apiUrl, reqData, {
...canshuOpt,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
}
__parse_method_type(type) {
return type;
}
/**
* GET 请求
*/
flagGet() {
const argumentsArr = arguments;
return this.unifyApi('flag', 'GET', argumentsArr);
}
urlGet() {
const argumentsArr = arguments;
return this.unifyApi('url', 'GET', argumentsArr);
}
/**
* POST 请求
*/
flagPost() {
const argumentsArr = arguments;
return this.unifyApi('flag', 'POST', argumentsArr);
}
urlPost() {
const argumentsArr = arguments;
return this.unifyApi('url', 'POST', argumentsArr);
}
/**
* PUT 请求
*/
flagPut() {
const argumentsArr = arguments;
return this.unifyApi('flag', 'PUT', argumentsArr);
}
urlPut() {
const argumentsArr = arguments;
return this.unifyApi('url', 'PUT', argumentsArr);
}
/**
* PATCH 请求
*/
flagPatch() {
const argumentsArr = arguments;
return this.unifyApi('flag', 'PATCH', argumentsArr);
}
urlPatch() {
const argumentsArr = arguments;
return this.unifyApi('url', 'PATCH', argumentsArr);
}
/**
* DELETE 请求
*/
flagDel() {
const argumentsArr = arguments;
return this.unifyApi('flag', 'DELETE', argumentsArr);
}
urlDel() {
const argumentsArr = arguments;
return this.unifyApi('url', 'DELETE', argumentsArr);
}
/* 文件上传通用 */
flagUpload() {
const argumentsArr = arguments;
return this.unifyApi('flag', 'UPLOAD', argumentsArr);
}
urlUpload() {
const argumentsArr = arguments;
return this.unifyApi('url', 'UPLOAD', argumentsArr);
}
/* 图片上传通用 */
flagUpImg() {
const argumentsArr = arguments;
return this.unifyApi('flag', 'UPLOAD', argumentsArr);
}
urlUpImg() {
const argumentsArr = arguments;
return this.unifyApi('url', 'UPLOAD', argumentsArr);
}
/**
* 统一请求
*/
unifyApi(flagOrUrl, methodType, argumentsArr) {
let _this = this;
let argNum = argumentsArr.length || 0;
if (argNum <= 0 || argNum > 3) {
let errorMsg = `-- ${methodType} : 参数为(1-3)个---`;
return new Promise((resolve, reject) => {
this.resetNetError({ message: errorMsg });
return reject({ message: errorMsg });
});
}
let apiUrl = '';
let apiUrlNoMsg = '';
if (flagOrUrl == 'flag') {
let apiFlag = argumentsArr[0];
if (typeof apiFlag === 'string') {
apiFlag = apiFlag || '';
apiUrl = apiFlag == '' ? '' : this.flagMap[apiFlag] || '';
}
apiUrlNoMsg = ' flag' + methodType + ':传入的标示 { ' + `${apiFlag}` + ' },未匹配到 apiUrl ';
}
if (flagOrUrl == 'url') {
apiUrl = argumentsArr[0];
if (typeof apiUrl === 'string') {
apiUrl = apiUrl || '';
}
apiUrlNoMsg = ' 未匹配到 apiUrl ';
}
if (apiUrl == '') {
return new Promise((resolve, reject) => {
this.resetNetError({ message: apiUrlNoMsg });
return reject({ message: apiUrlNoMsg });
});
}
// 如果传回一个
if (argNum == 1) {
return function (reqData) {
return _this.apiAll(methodType, apiUrl, reqData);
};
} else if (argNum == 2 || argNum == 3) {
let reqData = {};
let arg2Val = argumentsArr[1];
let arg2Type = Object.prototype.toString.call(arg2Val);
// let argType2_2 = typeof argumentsArr[1] === 'object';
if (arg2Type === '[object String]' || arg2Type === '[object Number]') {
let isEndIdStr = String(arg2Val).trim();
if (/^\d+$/.test(isEndIdStr)) {
if (!apiUrl.endsWith('/')) {
apiUrl += '/';
}
apiUrl += isEndIdStr; // 拼接时保留大整数精度
}
if (argNum == 3) {
let arg3Val = argumentsArr[2];
let arg3Type = Object.prototype.toString.call(arg3Val);
if (arg3Type === '[object Object]') {
reqData = arg3Val || {};
}
}
} else if (arg2Type === '[object Object]') {
reqData = arg2Val || {};
} else if (arg2Type === '[object FormData]') {
reqData = arg2Val || new FormData();
}
return _this.apiAll(methodType, apiUrl, reqData);
} else {
return new Promise((resolve, reject) => {
return reject({ message: ' 请求错误 ' });
});
}
}
}
export default RequestClass;