UNPKG

@tanshenghu/web-utils

Version:

web公共方法

750 lines (658 loc) 24.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.$getScript = exports.$jsonp = exports.$patch = exports.$put = exports.$post = exports.$head = exports.$delete = exports.$get = exports.Ajax = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* eslint-disable */ /** ** @Author: 谭生虎 TanShenghu tanshenghu@163.com ** @Update: 2018-05-10 ** @Description: ajax/fetch/socket/getScript数据请求方法封装 不支持jsonp如果后期有这需求可以添加 ** 因在request添加cookie, conent-type等字段信息所以只适合熙牛项目 ** special: intactModel<取整个respnse数据> customTip<自定义异常提示框> noHeaders<不带header信息> cover<默认无,传false不需要loading层> duration<提示框延迟关闭> ** hasFetchLoading=false<项目不需要loading层> */ var _xmlhttprequest = require('./xmlhttprequest'); Object.defineProperty(exports, 'Ajax', { enumerable: true, get: function get() { return _interopRequireDefault(_xmlhttprequest).default; } }); var _common = require('../common'); var _common2 = _interopRequireDefault(_common); var _orderly = require('../orderly'); var _orderly2 = _interopRequireDefault(_orderly); var _style = require('./style'); var _style2 = _interopRequireDefault(_style); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var isType = _common2.default.isType; var G = globalThis; var webConfig = G.webConfig || {}; var fetchingCount = void 0; var coverElement = null; var DATATYPES = ['json', 'text', 'blob', 'arrayBuffer']; // 数据流转换类型 var noop = function noop() {}; var hasSupperAbort = !!G.AbortController; var baseUrl = G.localStorage.getItem('ajaxBaseUrl'); var aloneBaseUrl = G.localStorage.getItem('ajaxAloneBaseUrl'); var defaultHeaders = {}; var injectBeforeSend = void 0; var injectResponseCallback = void 0; var injectResponseErrorCallback = void 0; var defaultFetchOptions = {}; var request = function request(options) { var _options$url = options.url, url = _options$url === undefined ? location.pathname : _options$url, _options$type = options.type, method = _options$type === undefined ? 'get' : _options$type, _options$data = options.data, data = _options$data === undefined ? {} : _options$data, _options$headers = options.headers, headers = _options$headers === undefined ? {} : _options$headers, _options$dataType = options.dataType, dataType = _options$dataType === undefined ? 'json' : _options$dataType, _options$special = options.special, special = _options$special === undefined ? {} : _options$special, _options$beforeSend = options.beforeSend, beforeSend = _options$beforeSend === undefined ? noop : _options$beforeSend, _options$success = options.success, success = _options$success === undefined ? noop : _options$success, _options$error = options.error, error = _options$error === undefined ? noop : _options$error, _options$complete = options.complete, complete = _options$complete === undefined ? noop : _options$complete, _options$option = options.option, option = _options$option === undefined ? {} : _options$option; var isMockDev = G.location.hostname.indexOf('mock.') > -1; special.duration = special.duration || 4000; dataType = DATATYPES.indexOf(dataType) > -1 ? dataType : 'text'; url = absUrl(url); method = method.toUpperCase(); var needUrl2Params = method === 'GET' || method === 'HEAD' || method === 'DELETE'; var baseHeaders = { accept: 'application/json' }; var mixHeaders = _extends({}, baseHeaders, method === 'POST' || method === 'PUT' || method === 'PATCH' ? { 'content-type': 'application/json; charset=UTF-8' } : {}, defaultHeaders, headers); var isFormData = data instanceof FormData; if (isFormData) { delete mixHeaders['content-type']; // /form-urlencoded|form-data/ 'multipart/form-data'; } var body = isFormData ? needUrl2Params ? formDataFormat(data) : data : data; if (needUrl2Params) { // GET 方式问题修复 data中含有undefined值的字段会传给后端,所以数据要转换一下过滤undefined值情况 url += (url.indexOf('?') > 0 ? '&' : '?') + queryString(body); url = url.replace(/(?:\?|\&)$/, ''); body = null; } else { body = typeof body === 'string' || isFormData ? body : JSON.stringify(formDataFormat(body)); } var response = void 0; beforeSend(); if (url.indexOf('//mocks.') > -1) { isMockDev = true; } var isHasCover = special.cover === true || isType(special.cover, 'undefined') && webConfig.hasFetchLoading === true; if (isHasCover) { protectedLayer('begin'); } // 兼容那些不支持 AbortController 的浏览器, 备注:IE浏览器不支持 AbortController 不要传 signal if (!hasSupperAbort) { G.AbortController = function () { this.signal = 'error'; this.abort = function () {}; }; } var abortCtl = new AbortController(); var final = [url, Object.assign({ method: method, headers: isMockDev ? {} : special.noHeaders ? headers : mixHeaders, signal: abortCtl.signal, credentials: 'omit', // 防止有缓存, 尤其是像IE11用的是polyfill 会有严重缓存问题 cache: 'no-cache', body: body }, defaultFetchOptions, option)]; // IE11 会报错处理 if (!hasSupperAbort) { delete final[1].signal; } if (isType(injectBeforeSend, 'function')) { injectBeforeSend(final); } var fetchRes = fetch(new (Function.prototype.bind.apply(Request, [null].concat(final)))()).then(function (res) { response = res; // 404 500状态处理 if (res.ok === false) { throw new Error(res.status == 404 ? '系统网络异常,请稍后再试' : '系统繁忙,请稍后再试'); } return res[dataType](); }).then(function (res) { // 业务事务处理 if (typeof injectResponseCallback === 'function') { injectResponseCallback({ resModel: res, options: options, response: response, alertMsg: alertMsg, errMsg: dealErrMsg(res.message || res.msg) || '系统繁忙,请稍后再试!' }); } return res; }).then(function (res) { var activeData = $ajax.bodyField ? res[$ajax.bodyField] : res; success(activeData, res, response); return isType(res) !== 'Object' && isType(res) !== 'Array' || special.intactModel === true ? res : activeData; }, function (err) { // 业务事务处理 if (typeof injectResponseErrorCallback === 'function') { injectResponseErrorCallback({ err: err, options: options, alertMsg: alertMsg, response: response }); } error(err, response); console.warn('获取接口数据产生异常:', err && err.message); }).finally(function (res) { if (isHasCover) { protectedLayer('done'); } complete(res); return res; }); if (hasSupperAbort) { fetchRes.abort = abortCtl.abort.bind(abortCtl); } return fetchRes; }; /** * 如果有一些自定义提示框 想获取整个response数据情况最好走ajax方法 * @param {object} options - 参数对象 */ var $ajax = function $ajax(options) { return request(options); }; /** * 设置接口主域名 * @param {string} ajaxBaseUrl - 接口域名 * @param {object} alone - 某些特殊的后端服务 单独配置 * * @api public */ $ajax.setBaseUrl = function (ajaxBaseUrl, alone) { var cacheBaseUrl = G.localStorage.getItem('ajaxBaseUrl'); var cacheAloneBaseUrl = JSON.parse(G.localStorage.getItem('ajaxAloneBaseUrl')) || alone; ajaxBaseUrl = cacheBaseUrl || ajaxBaseUrl; if (ajaxBaseUrl && typeof ajaxBaseUrl === 'string') { baseUrl = ajaxBaseUrl.indexOf('//') === -1 ? '//' + ajaxBaseUrl : ajaxBaseUrl; } if (isType(cacheAloneBaseUrl, 'array') && cacheAloneBaseUrl.length) { aloneBaseUrl = cacheAloneBaseUrl; } }; /** * fetch方法一些配置及属性设置 * @param {string} key - 字段名称 * @param {any} value - 字段对应的值 * @param {any} value2 - 字段对应的值 * * @api public */ $ajax.set = function (key, value, value2) { _common2.default.seek() /** * 设置baseUrl */ .equal(key === 'setBaseUrl', function () { $ajax.setBaseUrl(value, value2); }) /** * 设置接口中是否可带cookie */ .equal(key === 'credentials', function () { defaultFetchOptions.credentials = value; }) /** * 重置fetch默认配置参数对象 */ .equal(key === 'fetchOptions', function () { defaultFetchOptions = value; }) /** * 设置接口主体字段 */ .equal(key === 'bodyField', function () { $ajax.bodyField = value; }) /** * else */ .else(function () {}) /** * 调用并设置值 */ .get()(); }; /** * 获取接口主域名 * @param {boolean} [earnest] - 是否采用自动检测取host方法 */ $ajax.getBaseUrl = function () { var earnest = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; return earnest ? baseUrl || location.protocol + '//' + location.host : baseUrl; }; /** * 接口请求之前最后的拦截器 * @param {function} callback - 接口请求之前公共拦截器 */ $ajax.injectBeforeSend = function (callback) { if (isType(callback, 'function')) { injectBeforeSend = callback; } }; /** * 注入项目公用headers * @param {object} headers - 注入接口请求报文header */ $ajax.injectHeaders = function (headers) { if (isType(headers, 'object')) { defaultHeaders = Object.assign({}, defaultHeaders, headers); } }; $ajax.uninjectHeaders = function () { defaultHeaders = {}; }; /** * 注入共性事务处理方法 偏业务类型 * @param {function} callback - 回调事务处理 */ $ajax.injectResponse = function (callback, errorCallback) { if (typeof callback === 'function') { injectResponseCallback = callback; } if (typeof errorCallback === 'function') { injectResponseErrorCallback = errorCallback; } }; $ajax.appendStyle = addStyles; /** * 提供内部某些常用的辅助方法 */ $ajax.querystring = queryString; /** * 加载远程CSS,JS资源文件 * @param {string | array} attachSrc - js或者css服务端或cdn远程地址 * @param {function} cb - 加载成功之后回调 * @param {boolean} remove - 是否移除 */ var $getScript = function $getScript(attachSrc) { var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; var remove = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var loadCount = 0; var doc = G.document; var ohead = doc.documentElement.firstElementChild || doc.getElementsByTagName('head')[0]; var inspect = function inspect(type, src) { // 不考虑低版本浏览 提高性能就不用for循环了 return doc.querySelector(type === 'script' ? 'script[src="' + src + '"]' : 'link[href="' + src + '"]') === null; }; var addAttach = function addAttach(src, _ref) { var resolve = _ref.resolve, reject = _ref.reject; var extname = _common2.default.getRequest(src).extname; var type = /\.js$|\.js\?/.test(src) || extname === 'js' ? 'script' : /\.css$|\.css\?/.test(src) || extname === 'css' ? 'link' : null; if (!type) { throw new Error('请传入js或者css地址'); } if ($getScript.debug && !inspect(type, src)) { console.log('已经检测到之前有添加过该文件', type, src); return false; } var os = doc.createElement(type); os.onload = function () { loadCount++; if (Array.isArray(attachSrc) && attachSrc.length === loadCount || typeof attachSrc === 'string') { resolve(); cb(); } remove === true && type === 'script' && ohead.removeChild(os); }; os.onerror = function (err) { reject(err); }; if (type === 'script') { os.async = true; os.src = src; ohead.appendChild(os); } else { os.setAttribute('rel', 'stylesheet'); os.href = src; ohead.insertBefore(os, ohead.getElementsByTagName('title')[0]); } }; return new Promise(function (resolve, reject) { if (Array.isArray(attachSrc)) { attachSrc.forEach(function (srcUrl) { addAttach(srcUrl, { resolve: resolve, reject: reject }); }); } else if (typeof attachSrc === 'string') { addAttach(attachSrc, { resolve: resolve, reject: reject }); } else { throw new Error('传入的参数类型不正确!'); } }); }; /** * 将对象format成为url中参数格式 * @param {object} params - 对象 * * @api private */ function queryString(params) { params = _common2.default.clone(params); Object.keys(params).forEach(function (item) { if (_common2.default.isType(params[item], 'array') || _common2.default.isType(params[item], 'object')) { params[item] = JSON.stringify(params[item]); } }); if (G.URLSearchParams) { return new G.URLSearchParams(params).toString(); } var result = ''; var encode = function encode(v) { return typeof v === 'string' ? v.replace(/\&/gm, '%26').replace(/\?/gm, '%3F') : v; }; Object.keys(params).forEach(function (v) { result += '&' + v + '=' + encode(params[v]); }); return result.slice(1); } /** * FormData 格式化处理 */ function formDataFormat(data) { if (isType(data, 'formData')) { var result = {}; data.forEach(function (v, k) { result[k] = v; }); return result; } return data; } /** * 弹框提示 * @api private */ var alertMsg = function alertMsg(type, msg, duration) { var cb = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : noop; // type 1, 2 var popup = G.document.getElementById(type === 1 ? 'fetch-msg-tip' : 'fetch-err-tip'); var callfn = function callfn() { if (popup) { var delay = 0; if (type === 2) { popup.className = popup.className.replace('bounce', 'zoomOut'); delay = 820; } setTimeout(function () { if (popup) { G.document.body.removeChild(popup); popup = null; } }, delay); } cb(); }; if (!popup) { popup = G.document.createElement('div'); popup.id = type === 1 ? 'fetch-msg-tip' : 'fetch-err-tip'; G.document.body.appendChild(popup); if (type === 1) { popup.innerHTML = '<div class="popup-box"><div class="dialog-title">\u7CFB\u7EDF\u6E29\u99A8\u63D0\u793A</div><div class="dialog-content">' + msg + '</div><div class="dialog-handler"><button onclick="document.getElementById(\'fetch-msg-tip\').ecb()">\u786E\u5B9A</button></div></div>'; } else { popup.className = (popup.className || '') + 'animate__animated animate__bounce'; popup.innerHTML = '<div class="popup-box"><div class="dialog-title"><a href="javascript:;" class="close-btn" onclick="document.getElementById(\'fetch-err-tip\').ecb()">&times;</a></div><div class="dialog-content"><i class="icon-shibai"><svg viewBox="64 64 896 896" focusable="false" class="" data-icon="exclamation-circle" width="35px" height="35px" fill="#f1993b" aria-hidden="true"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 688a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm24-112h48c4.4 0 8-3.6 8-8V296c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8z"></path></svg></i><div class="content-text">' + msg + '</div></div></div>'; // popup.style.width = Math.min(popup.querySelector('.content-text').offsetWidth+90,234+90)+'px'; popup.style.height = Math.max(popup.querySelector('.dialog-content').offsetHeight + 38, 75) + 'px'; duration > 0 && setTimeout(function () { callfn(); }, 4000); // 自动关闭 } popup.ecb = callfn; } else { var msgTipPop = G.document.querySelector('#fetch-msg-tip .dialog-content'); if (msgTipPop) { msgTipPop.innerHTML = msg; popup.ecb = callfn; } } }; // 对error message各种错误格式的兼容处理 var dealErrMsg = function dealErrMsg(msg) { if (!msg) { return msg; } if (typeof msg === 'string' && msg.indexOf('[') === 0 && msg.lastIndexOf(']') === msg.length - 1) { try { msg = JSON.parse(msg); } catch (er) {} } if (Array.isArray(msg)) { if (isType(msg[0], 'string') && msg[0].indexOf('{') === 0 && msg[0].lastIndexOf('}') === msg[0].length - 1) { msg = msg.map(function (err) { return JSON.parse(err); }); } if (isType(msg[0], 'object') && msg[0].value) { msg = msg.map(function (err, index) { return msg.length === 1 ? err.value : index + 1 + '\u3001' + err.value; }).join(' '); } else { msg = msg.map(function (err, index) { return msg.length === 1 ? err : index + 1 + '\u3001' + err; }).join(' '); } } return msg; }; // 数据请求之前 加蒙板处理 var protectedLayerTimer1 = null; var protectedLayerTimer2 = null; var protectedLayer = function protectedLayer(actionType) { fetchingCount = fetchingCount || 0; var addCover = function addCover() { if (coverElement) { return false; } coverElement = G.document.createElement('div'); coverElement.id = 'fetch-loading-cover'; if (!G.document.getElementById('fetch-loading-cover')) { G.document.body.appendChild(coverElement); } clearTimeout(protectedLayerTimer1); protectedLayerTimer1 = setTimeout(function () { if (coverElement) { coverElement.className = (coverElement.className || '') + 'runAnt'; } }, 500); }; var removeCover = function removeCover() { if (fetchingCount < 1 && coverElement) { coverElement.className = ''; clearTimeout(protectedLayerTimer2); protectedLayerTimer2 = setTimeout(function () { if (fetchingCount < 1 && coverElement && G.document.getElementById('fetch-loading-cover')) { G.document.body.removeChild(coverElement); coverElement = null; } }, 700); } }; if (actionType === 'begin') { fetchingCount++; addCover(); } else if (actionType === 'done') { fetchingCount--; removeCover(); } }; exports.default = $ajax; /** * 接口GET调用方式 * @param {string} url - 接口地址 * @param {object} params - 接口参数 * @param {function} callback - 接口调用成功回调 * @param {string} dataType - 响应数据类型 */ var $get = exports.$get = function $get(url, params, callback, dataType) { if (isType(params, 'function')) { callback = params;params = {}; } if (isType(params, 'string') && DATATYPES.indexOf(params) > -1) { dataType = params;params = {}; } if (isType(callback, 'string') && DATATYPES.indexOf(callback) > -1) { dataType = callback;callback = undefined; } return request({ url: url, data: params, dataType: dataType, success: callback }); }; /** * 接口DELETE调用方式 * @param {string} url - 接口地址 * @param {object} params - 接口参数 * @param {function} callback - 接口调用成功回调 * @param {string} dataType - 响应数据类型 */ var $delete = exports.$delete = function $delete(url, params, callback, dataType) { if (isType(params, 'function')) { callback = params;params = {}; } if (isType(params, 'string') && DATATYPES.indexOf(params) > -1) { dataType = params;params = {}; } if (isType(callback, 'string') && DATATYPES.indexOf(callback) > -1) { dataType = callback;callback = undefined; } return request({ url: url, data: params, type: 'delete', dataType: dataType, success: callback }); }; /** * 接口HEAD调用方式 * @param {string} url - 接口地址 * @param {object} params - 接口参数 * @param {function} callback - 接口调用成功回调 * @param {string} dataType - 响应数据类型 */ var $head = exports.$head = function $head(url, params, callback, dataType) { if (isType(params, 'function')) { callback = params;params = {}; } if (isType(params, 'string') && DATATYPES.indexOf(params) > -1) { dataType = params;params = {}; } if (isType(callback, 'string') && DATATYPES.indexOf(callback) > -1) { dataType = callback;callback = undefined; } return request({ url: url, data: params, type: 'head', dataType: dataType, success: callback }); }; /** * 接口POST调用方式 * @param {string} url - 接口地址 * @param {object} params - 接口参数 * @param {function} callback - 接口调用成功回调 * @param {string} dataType - 响应数据类型 */ var $post = exports.$post = function $post(url, params, callback, dataType) { if (isType(params, 'function')) { callback = params;params = {}; } if (isType(params, 'string') && DATATYPES.indexOf(params) > -1) { dataType = params;params = {}; } if (isType(callback, 'string') && DATATYPES.indexOf(callback) > -1) { dataType = callback;callback = undefined; } return request({ url: url, data: params, type: 'post', dataType: dataType, success: callback }); }; /** * 接口PUT调用方式 * @param {string} url - 接口地址 * @param {object} params - 接口参数 * @param {function} callback - 接口调用成功回调 * @param {string} dataType - 响应数据类型 */ var $put = exports.$put = function $put(url, params, callback, dataType) { if (isType(params, 'function')) { callback = params;params = {}; } if (isType(params, 'string') && DATATYPES.indexOf(params) > -1) { dataType = params;params = {}; } if (isType(callback, 'string') && DATATYPES.indexOf(callback) > -1) { dataType = callback;callback = undefined; } return request({ url: url, data: params, type: 'put', dataType: dataType, success: callback }); }; /** * 接口PATCH调用方式 * @param {string} url - 接口地址 * @param {object} params - 接口参数 * @param {function} callback - 接口调用成功回调 * @param {string} dataType - 响应数据类型 */ var $patch = exports.$patch = function $patch(url, params, callback, dataType) { if (isType(params, 'function')) { callback = params;params = {}; } if (isType(params, 'string') && DATATYPES.indexOf(params) > -1) { dataType = params;params = {}; } if (isType(callback, 'string') && DATATYPES.indexOf(callback) > -1) { dataType = callback;callback = undefined; } return request({ url: url, data: params, type: 'patch', dataType: dataType, success: callback }); }; /** * jsonp实现方案 * @param {string} url - 接口地址 * @param {object} [params] - 接口参数 * @param {string} [callbackName="callback"] - callback名称,一般情况下不需要特定,用默认值即可 */ var $jsonp = exports.$jsonp = function $jsonp(url) { var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var callbackName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'callback'; var cbName = 'tsh_call_' + Date.now().toString(32); var resModel = void 0; G[cbName] = function (data) { resModel = data; }; params.extname = 'js'; params[callbackName] = cbName; return $getScript(_common2.default.concatSearch(url, params)).then(function () { delete G[cbName]; return resModel; }, function (er) { delete G[cbName]; return er; }); }; exports.$getScript = $getScript; function absUrl(url) { if (url.indexOf('//') === -1) { var chost = Array.isArray(aloneBaseUrl) && aloneBaseUrl.find(function (item) { var reg = new RegExp(item.test); return reg.test(url); }); if (chost) { url = chost.host + url; } else if (baseUrl) { url = baseUrl + url; } else { url = location.origin + url; } } return url; } function addStyles(colors) { if (!document.getElementById('fetch-styles')) { var title = document.getElementsByTagName('title'); _common2.default.appendStyle((0, _style2.default)(colors), { id: 'fetch-styles', before: title[0] }); } } (0, _orderly2.default)(function () { addStyles(); }, { sleep: 80, type: 'debounce' })();