UNPKG

@zibu/common

Version:

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

265 lines (243 loc) 10.5 kB
import * as Enum from './Enum'; import HttpRequest from './HttpRequest'; const _host = typeof __HOST__ === 'string' ? __HOST__ : ''; /** * 定义AjaxService类 */ class AjaxService { /** * AjaxService类构造函数 * @param {String} url RESTful格式的请求地址(默认值:__HOST__ + '{/api}{/module}{/action}{/id}') * @param {String} contentType 发送形式,默认form表单(json、form、formData) * @param {String} host 请求服务器域名 * @param {Boolean} isReturnWholeResponse 是否返回完整的response,默认只返回body(默认:false) */ constructor(url, contentType = 'form', host = _host, isReturnWholeResponse = false) { this.requestInstance = null; // HttpRequest实例 this.cancel = () => {}; // 想取消ajax请求时,调用此方法,只有在h5页面可以取消 this.originalUrl = url || host + '{/api}{/version}{/module}{/action}{/id}'; // +运算符的优先级要比||运算符优先级高 this.sections = []; // RESTful格式地址中动态部分 this.isReturnWholeResponse = isReturnWholeResponse; this.init(contentType); } static ContentType = Enum.ContentType; /** * 初始化AjaxService * @param {String} contentType 请求Header中的Content-Type */ init(contentType) { const httpRequest = new HttpRequest(contentType); this.requestInstance = httpRequest.request; this.cancel = httpRequest.cancelFun; // 设置Content-Type this.setHeader('Content-Type', httpRequest.contentType); // 注入response钩子函数 this.injectResponseHook( response => { return this.isReturnWholeResponse ? response : response.data; }, error => { if (HttpRequest.isCancel(error)) { // 取消ajax请求 return { type: 'cancel', body: error }; } if (error.request) { // ajax请求错误 return { type: 'request', body: error.request }; } if (error.response) { // ajax响应错误 return { type: 'response', body: error.response }; } return { type: 'other', body: error }; } ); // 分解原始RESTful格式地址 const reg = /\{\/([^}]+)\}/g; // 因为str.match方法返回的结果只有匹配的内容,没有每一个匹配中正则表达式小括号内的内容 // 所以使用reg.exec方法。 while (reg.lastIndex < this.originalUrl.length) { const section = reg.exec(this.originalUrl); if (!section) { break; } this.sections.push(section); } // this.initHTTPMethod(); } /** * 设置当前实例化对象指定请求类型附加的header,如果未指定类型,则默认全部请求都附加指定header * @param {String} key header的key * @param {String} value header的value * @param {String} requestType 请求类型('post', 'delete', 'put', 'patch', 'get') */ setHeader(key, value, requestType) { if (key && value) { requestType = requestType || 'common'; const header = this.requestInstance.defaults.headers[requestType]; header[key] = value; } } /** * 注入请求钩子函数 * @param {Function} hookFunction 请求钩子函数 */ injectRequestHook(hookFunction) { if (typeof hookFunction === 'function') { this.requestInstance.interceptors.request.use(config => { return hookFunction(config); }); } } /** * 注入响应钩子函数 * @param {Function} resolveHook 成功钩子函数 * @param {Function} rejectHook 失败钩子函数 */ injectResponseHook(resolveHook, rejectHook) { this.requestInstance.interceptors.response.use( response => { if (typeof resolveHook === 'function') { const returnValue = resolveHook(response); // 如果未返回值,则表示Ajax的钩子函数不需要返回内容 if (typeof returnValue !== 'undefined') { return returnValue; } } else { return response; } }, error => { if (typeof rejectHook === 'function') { const returnValue = rejectHook(error); // 如果未返回值,则表示Ajax的钩子函数不需要返回内容 if (typeof returnValue !== 'undefined') { if (returnValue instanceof Promise) { return returnValue; } return Promise.reject(returnValue); } } else { return Promise.reject(error); } } ); } /** * 将方法写到外层的原因:原先的执行方案是在构造函数中,调用init方法,init方法里初始化完requestInstance之后,执行initHTTPMethod,给this对象附加http请求方法,实际上并不是在原型链上定义方法 * 产生的问题:继承类无法通过覆写的方式重写方法,只能通过在继承类的构造函数中覆盖this对象里附加的方法 * 解决方案:改成使用原型链的方式定义http方法 * 原先的代码 * initHTTPMethod() { * ['post', 'delete', 'put', 'patch', 'get'].forEach(key => { * if (typeof this.requestInstance[key] === 'function') { * this[key] = (urlObj, param, config) => this.requestInstance[key](this.urlMatch(urlObj), param, config); * } * }); * } */ /** * 发送post请求 * @param {Object} urlObj 请求地址对象 * @param {Object} param 请求参数 * @param {Object} config [请求配置项](https://github.com/axios/axios#instance-methods | https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html) * @returns {Promise} 返回Promise对象 */ post(urlObj, param, config) { return this.execHttpRequest('post', urlObj, param, config); } /** * 发送delete请求 * @param {Object} urlObj 请求地址对象 * @param {Object} param 请求参数 * @param {Object} config [请求配置项](https://github.com/axios/axios#instance-methods | https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html) * @returns {Promise} 返回Promise对象 */ delete(urlObj, param, config) { return this.execHttpRequest('delete', urlObj, param, config); } /** * 发送put请求 * @param {Object} urlObj 请求地址对象 * @param {Object} param 请求参数 * @param {Object} config [请求配置项](https://github.com/axios/axios#instance-methods | https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html) * @returns {Promise} 返回Promise对象 */ put(urlObj, param, config) { return this.execHttpRequest('put', urlObj, param, config); } /** * 发送patch请求 * @param {Object} urlObj 请求地址对象 * @param {Object} param 请求参数 * @param {Object} config [请求配置项](https://github.com/axios/axios#instance-methods | https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html) * @returns {Promise} 返回Promise对象 */ patch(urlObj, param, config) { return this.execHttpRequest('patch', urlObj, param, config); } /** * 发送get请求 * @param {Object} urlObj 请求地址对象 * @param {Object} param 请求参数 * @param {Object} config [请求配置项](https://github.com/axios/axios#instance-methods | https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html) * @returns {Promise} 返回Promise对象 */ get(urlObj, param, config) { return this.execHttpRequest('get', urlObj, param, config); } /** * 执行HTTP请求 * @param {String} methodName 请求方法名 * @param {Object} urlObj 请求地址对象 * @param {Object} param 请求参数 * @param {Object} config [请求配置项](https://github.com/axios/axios#instance-methods | https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html) * @returns {Promise} 返回Promise对象 */ execHttpRequest(methodName, urlObj, param, config) { if (this.requestInstance && typeof this.requestInstance[methodName] === 'function') { return this.requestInstance[methodName](this.urlMatch(urlObj), param, config); } throw new Error('AjaxService:请求的方法不存在'); } /** * 将请求地址对象匹配到原始请求地址上 * @param {Object} urlObj 请求地址对象 * @returns {String} 返回匹配后的地址 */ urlMatch(urlObj) { let url = this.originalUrl; // 如果请求的方法里提供了host,则替换掉实例化时传递的服务器地址 if (Object.prototype.hasOwnProperty.call(urlObj, 'host')) { // 找出第一个{之前的所有内容 const httpReg = /^[^{]+/; // 用新提供的host替换掉已存在的host url = url.replace(httpReg, urlObj.host); } this.sections.forEach(section => { const key = section[1]; let value = Object.prototype.hasOwnProperty.call(urlObj, key) ? urlObj[key] : this[key]; if (value) { value = '/' + value; } else { value = ''; } const reg = new RegExp(section[0]); url = url.replace(reg, value); }); return url; } } export default AjaxService;