UNPKG

@zibu/common

Version:

通用逻辑功能模块。包含AjaxService、clone、cookie、dataFormat、queryString、clipboard

125 lines (113 loc) 4.93 kB
import { ContentType } from './Enum'; import axios from 'axios'; // import WXHttpRequest from './WXHttpRequest'; /** * 根据当前运行环境生成相应的发送Http请求对象 */ export default class HttpRequest { /** * 根据当前运行环境生成相应的发送Http请求对象HttpRequest类构造函数 * @param {String} contentType 发送形式,默认form表单(json、form、formData) */ constructor(contentType) { // 为了兼容以前发布的版本,构造函数的参数仍然是String,所以需要用ContentType转换一下 // 因为枚举值是大写,所以需要统一转换成大写 contentType = contentType.toUpperCase(); this.contentType = ContentType[contentType]; this.request = null; this.cancelFun = () => {}; // 只有在h5页面有效 this.cancelToken = ''; // 是否是微信小程序 this.isMiniApp = typeof wx === 'object' && typeof wx.canIUse === 'function' && wx.canIUse('request') && typeof wx.request === 'function'; if (this.isMiniApp) { this.request = new WXHttpRequest(); } else { // 设置CancelToken并实例化axios对象 const cancelToken = new axios.CancelToken(fnCancel => { this.cancelFun = fnCancel; }); this.request = axios.create({ cancelToken }); this.request.interceptors.request.use(config => { const parameter = config.data; if (typeof parameter !== 'object' || !parameter) { return config; } config.data = this.processRequestParam(parameter, config.headers.common['Content-Type']); return config; }); // 附加的参数是地址栏?后面,所以参数要放到config.params里 const getFun = this.request.get; this.request.get = (url, param, config = {}) => { return getFun.call(this.request, url, { params: param, ...config }); }; const deleteFun = this.request.delete; this.request.delete = (url, param, config = {}) => { return deleteFun.call(this.request, url, { params: param, ...config }); }; } } /** * 处理请求参数 * @param {Object} parameter 请求参数 * @param {Enum<ContentType>} headersContentType headers中临时设置的Content-Type * @returns {Object} 返回处理后的参数 */ processRequestParam(parameter, headersContentType) { // 实现了 FormData 接口的对象可以直接在for...of结构中使用,而不需要调用parameter.entries()方法 let entries = parameter; const isFormDataType = parameter.constructor === FormData; if (!isFormDataType) { entries = Object.entries(parameter); } const newParam = Array.isArray(parameter) ? [] : {}; const specialParams = {}; for (const [key, value] of entries) { // 文件类型因为不是值类型会被序列化没了,所以先记录下来序列化完后,再还原回来 if (value && value.constructor === File) { specialParams[key] = value; } else { newParam[key] = value; } } // 利用JSON.stringify去掉undefined和function类型的值 parameter = JSON.parse(JSON.stringify(newParam)); // 还原特殊参数 Object.keys(specialParams).forEach(key => { parameter[key] = specialParams[key]; }); /** * 如果发送请求是FORM表单,Axios不会对FORM表单的请求参数进行转换,直接转换成FORM表单格式即可。 * 不是FORM表单的话,再判断原有参数类型是不是FormData,如果是,还需要将JSON转换成FormData */ if ((headersContentType || this.contentType) === ContentType.FORM) { const params = []; Object.keys(parameter).forEach(key => { const value = parameter[key]; params.push(`${key}=${value}`); }); parameter = params.join('&'); } else if (isFormDataType) { const formDataParam = new FormData(); Object.keys(parameter).forEach(key => formDataParam.append(key, parameter[key])); parameter = formDataParam; } return parameter; } /** * 判断是否是手动取消导致请求出错 * @param {Object} error 取消出错对象 * @return {Boolean} 返回是否是手动取消导致请求出错 */ static isCancel(error) { // if (this.isMiniApp) { // return false; // } return axios.isCancel(error); } }