UNPKG

@10yun/cv-js-utils

Version:

常用 js-utils 工具类库

636 lines (620 loc) 18.5 kB
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;