UNPKG

wodax-umi-request

Version:

A request tool based on fetch. Cloned from umi-request

1,159 lines (956 loc) 33.4 kB
import { parse, stringify } from 'query-string'; import 'isomorphic-fetch'; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var defineProperty = _defineProperty; function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { defineProperty(target, key, source[key]); }); } return target; } var objectSpread = _objectSpread; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var classCallCheck = _classCallCheck; function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var createClass = _createClass; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var _typeof_1 = createCommonjsModule(function (module) { function _typeof2(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); } function _typeof(obj) { if (typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol") { module.exports = _typeof = function _typeof(obj) { return _typeof2(obj); }; } else { module.exports = _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj); }; } return _typeof(obj); } module.exports = _typeof; }); function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } var arrayWithoutHoles = _arrayWithoutHoles; function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } var iterableToArray = _iterableToArray; function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } var nonIterableSpread = _nonIterableSpread; function _toConsumableArray(arr) { return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread(); } var toConsumableArray = _toConsumableArray; // 返回一个组合了所有插件的“插件” function compose(middlewares) { if (!Array.isArray(middlewares)) throw new TypeError('Middlewares must be an array!'); var middlewaresLen = middlewares.length; for (var i = 0; i < middlewaresLen; i++) { if (typeof middlewares[i] !== 'function') { throw new TypeError('Middleware must be componsed of function'); } } return function wrapMiddlewares(params, next) { var index = -1; function dispatch(i) { if (i <= index) { return Promise.reject(new Error('next() should not be called multiple times in one middleware!')); } index = i; var fn = middlewares[i] || next; if (!fn) return Promise.resolve(); try { return Promise.resolve(fn(params, function () { return dispatch(i + 1); })); } catch (err) { return Promise.reject(err); } } return dispatch(0); }; } var Onion = /*#__PURE__*/ function () { function Onion(defaultMiddlewares) { classCallCheck(this, Onion); if (!Array.isArray(defaultMiddlewares)) throw new TypeError('Default middlewares must be an array!'); this.middlewares = toConsumableArray(defaultMiddlewares); } createClass(Onion, [{ key: "use", // 内置内核中间件长度 value: function use(newMiddleware) { var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { global: false, core: false }; var core = false; var global = false; if (typeof opts === 'number') { if (process && process.env && process.env.NODE_ENV === 'development') { console.warn('use() options should be object, number property would be deprecated in future,please update use() options to "{ core: true }".'); } core = true; global = false; } else if (_typeof_1(opts) === 'object' && opts) { global = opts.global || false; core = opts.core || false; } // 全局中间件 if (global) { Onion.globalMiddlewares.splice(Onion.globalMiddlewares.length - Onion.defaultGlobalMiddlewaresLength, 0, newMiddleware); return; } // 内核中间件 if (core) { Onion.coreMiddlewares.splice(Onion.coreMiddlewares.length - Onion.defaultCoreMiddlewaresLength, 0, newMiddleware); return; } // 实例中间件 this.middlewares.push(newMiddleware); } }, { key: "execute", value: function execute() { var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var fn = compose([].concat(toConsumableArray(this.middlewares), toConsumableArray(Onion.globalMiddlewares), toConsumableArray(Onion.coreMiddlewares))); return fn(params); } }]); return Onion; }(); Onion.globalMiddlewares = []; Onion.defaultGlobalMiddlewaresLength = 0; Onion.coreMiddlewares = []; Onion.defaultCoreMiddlewaresLength = 0; function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } var assertThisInitialized = _assertThisInitialized; function _possibleConstructorReturn(self, call) { if (call && (_typeof_1(call) === "object" || typeof call === "function")) { return call; } return assertThisInitialized(self); } var possibleConstructorReturn = _possibleConstructorReturn; var getPrototypeOf = createCommonjsModule(function (module) { function _getPrototypeOf(o) { module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } module.exports = _getPrototypeOf; }); var setPrototypeOf = createCommonjsModule(function (module) { function _setPrototypeOf(o, p) { module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } module.exports = _setPrototypeOf; }); function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) setPrototypeOf(subClass, superClass); } var inherits = _inherits; function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } var isNativeFunction = _isNativeFunction; var construct = createCommonjsModule(function (module) { function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { module.exports = _construct = Reflect.construct; } else { module.exports = _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } module.exports = _construct; }); var wrapNativeSuper = createCommonjsModule(function (module) { function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; module.exports = _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return construct(Class, arguments, getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } module.exports = _wrapNativeSuper; }); var MapCache = /*#__PURE__*/ function () { function MapCache(options) { classCallCheck(this, MapCache); this.cache = new Map(); this.timer = {}; this.maxCache = options.maxCache || 0; } createClass(MapCache, [{ key: "get", value: function get(key) { return this.cache.get(JSON.stringify(key)); } }, { key: "set", value: function set(key, value) { var _this = this; var ttl = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 60000; // 如果超过最大缓存数, 删除头部的第一个缓存. if (this.maxCache > 0 && this.cache.size >= this.maxCache) { var deleteKey = toConsumableArray(this.cache.keys())[0]; this.cache.delete(deleteKey); if (this.timer[deleteKey]) { clearTimeout(this.timer[deleteKey]); } } var cacheKey = JSON.stringify(key); this.cache.set(cacheKey, value); if (ttl > 0) { this.timer[cacheKey] = setTimeout(function () { _this.cache.delete(cacheKey); delete _this.timer[cacheKey]; }, ttl); } } }, { key: "delete", value: function _delete(key) { var cacheKey = JSON.stringify(key); delete this.timer[cacheKey]; return this.cache.delete(cacheKey); } }, { key: "clear", value: function clear() { this.timer = {}; return this.cache.clear(); } }]); return MapCache; }(); /** * 请求异常 */ var RequestError = /*#__PURE__*/ function (_Error) { inherits(RequestError, _Error); function RequestError(text, request) { var _this2; classCallCheck(this, RequestError); _this2 = possibleConstructorReturn(this, getPrototypeOf(RequestError).call(this, text)); _this2.name = 'RequestError'; _this2.request = request; return _this2; } return RequestError; }(wrapNativeSuper(Error)); /** * 响应异常 */ var ResponseError = /*#__PURE__*/ function (_Error2) { inherits(ResponseError, _Error2); function ResponseError(response, text, data, request) { var _this3; classCallCheck(this, ResponseError); _this3 = possibleConstructorReturn(this, getPrototypeOf(ResponseError).call(this, text || response.statusText)); _this3.name = 'ResponseError'; _this3.data = data; _this3.response = response; _this3.request = request; return _this3; } return ResponseError; }(wrapNativeSuper(Error)); /** * http://gitlab.alipay-inc.com/KBSJ/gxt/blob/release_gxt_S8928905_20180531/src/util/request.js#L63 * 支持gbk */ function readerGBK(file) { return new Promise(function (resolve, reject) { var reader = new FileReader(); reader.onload = function () { resolve(reader.result); }; reader.onerror = reject; reader.readAsText(file, 'GBK'); // setup GBK decoding }); } /** * 安全的JSON.parse */ function safeJsonParse(data) { var throwErrIfParseFail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var response = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var request = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; try { return JSON.parse(data); } catch (e) { if (throwErrIfParseFail) { throw new ResponseError(response, 'JSON.parse fail', data, request); } } // eslint-disable-line no-empty return data; } function timeout2Throw(msec, request) { return new Promise(function (_, reject) { setTimeout(function () { reject(new RequestError("timeout of ".concat(msec, "ms exceeded"), request)); }, msec); }); } // If request options contain 'cancelToken', reject request when token has been canceled function cancel2Throw(opt) { return new Promise(function (_, reject) { if (opt.cancelToken) { opt.cancelToken.promise.then(function (cancel) { reject(cancel); }); } }); } var toString = Object.prototype.toString; // Check env is browser or node function getEnv() { var env; // Only Node.JS has a process variable that is of [[Class]] process if (typeof process !== 'undefined' && toString.call(process) === '[object process]') { // For node use HTTP adapter env = 'NODE'; } if (typeof XMLHttpRequest !== 'undefined') { env = 'BROWSER'; } return env; } function isArray(val) { return _typeof_1(val) === 'object' && Object.prototype.toString.call(val) === '[object Array]'; } function isURLSearchParams(val) { return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; } function isDate(val) { return _typeof_1(val) === 'object' && Object.prototype.toString.call(val) === '[object Date]'; } function isObject(val) { return val !== null && _typeof_1(val) === 'object'; } function forEach2ObjArr(target, callback) { if (!target) return; if (_typeof_1(target) !== 'object') { target = [target]; } if (isArray(target)) { for (var i = 0; i < target.length; i++) { callback.call(null, target[i], i, target); } } else { for (var key in target) { if (Object.prototype.hasOwnProperty.call(target, key)) { callback.call(null, target[key], key, target); } } } } function getParamObject(val) { if (isURLSearchParams(val)) { return parse(val.toString()); } if (typeof val === 'string') { return [val]; } return val; } // 前后缀拦截 var addfix = function addfix(url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var prefix = options.prefix, suffix = options.suffix; if (prefix) { url = "".concat(prefix).concat(url); } if (suffix) { url = "".concat(url).concat(suffix); } return { url: url, options: options }; }; function fetchMiddleware(ctx, next) { if (!ctx) return next(); var _ctx$req = ctx.req; _ctx$req = _ctx$req === void 0 ? {} : _ctx$req; var _ctx$req$options = _ctx$req.options, options = _ctx$req$options === void 0 ? {} : _ctx$req$options, _ctx$req$url = _ctx$req.url, url = _ctx$req$url === void 0 ? '' : _ctx$req$url, cache = ctx.cache, responseInterceptors = ctx.responseInterceptors; var _options$timeout = options.timeout, timeout = _options$timeout === void 0 ? 0 : _options$timeout, _options$__umiRequest = options.__umiRequestCoreType__, __umiRequestCoreType__ = _options$__umiRequest === void 0 ? 'normal' : _options$__umiRequest, _options$useCache = options.useCache, useCache = _options$useCache === void 0 ? false : _options$useCache, _options$method = options.method, method = _options$method === void 0 ? 'get' : _options$method, params = options.params, ttl = options.ttl; if (__umiRequestCoreType__ !== 'normal') { if (process && process.env && process.env.NODE_ENV === 'development') { console.warn('__umiRequestCoreType__ is a internal property that use in umi-request, change its value would affect the behavior of request! It only use when you want to extend the request core.'); } return next(); } var adapter = fetch; if (!adapter) { throw new Error('Global fetch not exist!'); } // 从缓存池检查是否有缓存数据 var isBrowser = getEnv() === 'BROWSER'; var needCache = method.toLowerCase() === 'get' && useCache && isBrowser; if (needCache) { var responseCache = cache.get({ url: url, params: params }); if (responseCache) { responseCache = responseCache.clone(); responseCache.useCache = true; ctx.res = responseCache; return next(); } } var response; // 超时处理、取消请求处理 if (timeout > 0) { response = Promise.race([cancel2Throw(options), adapter(url, options), timeout2Throw(timeout, ctx.req)]); } else { response = Promise.race([cancel2Throw(options), adapter(url, options)]); } // 兼容老版本 response.interceptor responseInterceptors.forEach(function (handler) { /// Note:response 大部分特性是只读的,修改并没有意义,所以使用克隆方式 (sunzhifeng 2019.10.11) if (!!options["MODIFY_RESPONSE_OBJECT_TRY"]) { response = response.then(function (res) { return handler(res, options); }); } else { response = response.then(function (res) { handler(res.clone(), options); return res; }); } }); return response.then(function (res) { // 是否存入缓存池 if (needCache) { if (res.status === 200) { var copy = res.clone(); copy.useCache = true; cache.set({ url: url, params: params }, copy, ttl); } } ctx.res = res; return next(); }); } function parseResponseMiddleware(ctx, next) { var copy; return next().then(function () { if (!ctx) return; var _ctx$res = ctx.res, res = _ctx$res === void 0 ? {} : _ctx$res, _ctx$req = ctx.req, req = _ctx$req === void 0 ? {} : _ctx$req; var _ref = req || {}, _ref$options = _ref.options; _ref$options = _ref$options === void 0 ? {} : _ref$options; var _ref$options$response = _ref$options.responseType, responseType = _ref$options$response === void 0 ? 'json' : _ref$options$response, _ref$options$charset = _ref$options.charset, charset = _ref$options$charset === void 0 ? 'utf8' : _ref$options$charset, _ref$options$getRespo = _ref$options.getResponse, _ref$options$throwErr = _ref$options.throwErrIfParseFail, throwErrIfParseFail = _ref$options$throwErr === void 0 ? false : _ref$options$throwErr, _ref$options$parseRes = _ref$options.parseResponse, parseResponse = _ref$options$parseRes === void 0 ? true : _ref$options$parseRes; if (!parseResponse) { return; } if (!res || !res.clone) { return; } // 只在浏览器环境对 response 做克隆, node 环境如果对 response 克隆会有问题:https://github.com/bitinn/node-fetch/issues/553 copy = getEnv() === 'BROWSER' ? res.clone() : res; copy.useCache = res.useCache || false; // 解析数据 if (charset === 'gbk') { try { return res.blob().then(readerGBK).then(function (d) { return safeJsonParse(d, false, copy, req); }); } catch (e) { throw new ResponseError(copy, e.message, null, req); } } else if (responseType === 'json') { return res.text().then(function (d) { return safeJsonParse(d, throwErrIfParseFail, copy, req); }); } try { // 其他如text, blob, arrayBuffer, formData return res[responseType](); } catch (e) { throw new ResponseError(copy, 'responseType not support', null, req); } }).then(function (body) { if (!ctx) return; var _ctx$res2 = ctx.res, _ctx$req2 = ctx.req, req = _ctx$req2 === void 0 ? {} : _ctx$req2; var _ref2 = req || {}, _ref2$options = _ref2.options; _ref2$options = _ref2$options === void 0 ? {} : _ref2$options; var _ref2$options$getResp = _ref2$options.getResponse, getResponse = _ref2$options$getResp === void 0 ? false : _ref2$options$getResp; if (!copy) { return; } if (copy.status >= 200 && copy.status < 300) { // 提供源response, 以便自定义处理 if (getResponse) { ctx.res = { data: body, response: copy }; return; } ctx.res = body; return; } throw new ResponseError(copy, 'http error', body, req); }); } function simplePostMiddleware(ctx, next) { if (!ctx) return next(); var _ctx$req = ctx.req; _ctx$req = _ctx$req === void 0 ? {} : _ctx$req; var _ctx$req$options = _ctx$req.options, options = _ctx$req$options === void 0 ? {} : _ctx$req$options; var _options$method = options.method, method = _options$method === void 0 ? 'get' : _options$method; if (['post', 'put', 'patch', 'delete'].indexOf(method.toLowerCase()) === -1) { return next(); } var _options$requestType = options.requestType, requestType = _options$requestType === void 0 ? 'json' : _options$requestType, data = options.data; // 数据使用类axios的新字段data, 避免引用后影响旧代码, 如将body stringify多次 if (data) { var dataType = Object.prototype.toString.call(data); if (dataType === '[object Object]' || dataType === '[object Array]') { if (requestType === 'json') { options.headers = objectSpread({ Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' }, options.headers); options.body = JSON.stringify(data); } else if (requestType === 'form') { options.headers = objectSpread({ Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' }, options.headers); options.body = stringify(data); } } else { // 其他 requestType 自定义header options.headers = objectSpread({ Accept: 'application/json' }, options.headers); options.body = data; } } ctx.req.options = options; return next(); } function paramsSerialize(params, paramsSerializer) { var serializedParams; var jsonStringifiedParams; // 支持参数自动拼装,其他 method 也可用,不冲突 if (params) { if (paramsSerializer) { serializedParams = paramsSerializer(params); } else if (isURLSearchParams(params)) { serializedParams = params.toString(); } else { if (isArray(params)) { jsonStringifiedParams = []; forEach2ObjArr(params, function (item) { if (item === null || typeof item === 'undefined') { jsonStringifiedParams.push(item); } else { jsonStringifiedParams.push(isObject(item) ? JSON.stringify(item) : item); } }); serializedParams = stringify(jsonStringifiedParams); } else { jsonStringifiedParams = {}; forEach2ObjArr(params, function (value, key) { var jsonStringifiedValue = value; if (value === null || typeof value === 'undefined') { jsonStringifiedParams[key] = value; } else if (isDate(value)) { jsonStringifiedValue = value.toISOString(); } else if (isArray(value)) { jsonStringifiedValue = value; } else if (isObject(value)) { jsonStringifiedValue = JSON.stringify(value); } jsonStringifiedParams[key] = jsonStringifiedValue; }); var tmp = stringify(jsonStringifiedParams); serializedParams = tmp; } } } return serializedParams; } // 对请求参数做处理,实现 query 简化、 post 简化 function simpleGetMiddleware(ctx, next) { if (!ctx) return next(); var _ctx$req = ctx.req; _ctx$req = _ctx$req === void 0 ? {} : _ctx$req; var _ctx$req$options = _ctx$req.options, options = _ctx$req$options === void 0 ? {} : _ctx$req$options; var paramsSerializer = options.paramsSerializer, params = options.params; var _ctx$req2 = ctx.req; _ctx$req2 = _ctx$req2 === void 0 ? {} : _ctx$req2; var _ctx$req2$url = _ctx$req2.url, url = _ctx$req2$url === void 0 ? '' : _ctx$req2$url; // 将 method 改为大写 options.method = options.method ? options.method.toUpperCase() : 'GET'; // 设置 credentials 默认值为 same-origin,确保当开发者没有设置时,各浏览器对请求是否发送 cookies 保持一致的行为 // - omit: 从不发送cookies. // - same-origin: 只有当URL与响应脚本同源才发送 cookies、 HTTP Basic authentication 等验证信息.(浏览器默认值,在旧版本浏览器,例如safari 11依旧是omit,safari 12已更改) // - include: 不论是不是跨域的请求,总是发送请求资源域在本地的 cookies、 HTTP Basic authentication 等验证信息. options.credentials = options.credentials || 'same-origin'; // 支持类似axios 参数自动拼装, 其他method也可用, 不冲突. var serializedParams = paramsSerialize(params, paramsSerializer); ctx.req.originUrl = url; if (serializedParams) { var urlSign = url.indexOf('?') !== -1 ? '&' : '?'; ctx.req.url = "".concat(url).concat(urlSign).concat(serializedParams); } ctx.req.options = options; return next(); } var requestInterceptors = [addfix]; var responseInterceptors = []; // 初始化全局和内核中间件 var globalMiddlewares = [simplePostMiddleware, simpleGetMiddleware, parseResponseMiddleware]; var coreMiddlewares = [fetchMiddleware]; Onion.globalMiddlewares = globalMiddlewares; Onion.defaultGlobalMiddlewaresLength = globalMiddlewares.length; Onion.coreMiddlewares = coreMiddlewares; Onion.defaultCoreMiddlewaresLength = coreMiddlewares.length; var Core = /*#__PURE__*/ function () { function Core(initOptions) { classCallCheck(this, Core); this.onion = new Onion([]); this.fetchIndex = 0; // 【即将废弃】请求中间件位置 this.mapCache = new MapCache(initOptions); } createClass(Core, [{ key: "use", value: function use(newMiddleware) { var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { global: false, core: false }; this.onion.use(newMiddleware, opt); return this; } }, { key: "request", value: function request(url, options) { var onion = this.onion; var obj = { req: { url: url, options: options }, res: null, cache: this.mapCache, responseInterceptors: responseInterceptors }; if (typeof url !== 'string') { throw new Error('url MUST be a string'); } return new Promise(function (resolve, reject) { Core.dealRequestInterceptors(obj).then(function () { return onion.execute(obj); }).then(function () { resolve(obj.res); }).catch(function (error) { var errorHandler = obj.req.options.errorHandler; if (errorHandler) { try { var data = errorHandler(error, obj); resolve(data); } catch (e) { reject(e); } } else { reject(error); } }); }); } }], [{ key: "requestUse", value: function requestUse(handler) { if (typeof handler !== 'function') throw new TypeError('Interceptor must be function!'); requestInterceptors.push(handler); } }, { key: "responseUse", value: function responseUse(handler) { if (typeof handler !== 'function') throw new TypeError('Interceptor must be function!'); responseInterceptors.push(handler); } // 执行请求前拦截器 }, { key: "dealRequestInterceptors", value: function dealRequestInterceptors(ctx) { var reducer = function reducer(p1, p2) { return p1.then(function () { var ret = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; ctx.req.url = ret.url || ctx.req.url; ctx.req.options = ret.options || ctx.req.options; return p2(ctx.req.url, ctx.req.options); }); }; return requestInterceptors.reduce(reducer, Promise.resolve()).then(function () { var ret = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; ctx.req.url = ret.url || ctx.req.url; ctx.req.options = ret.options || ctx.req.options; return Promise.resolve(); }); } }]); return Core; }(); /** * 当执行 “取消请求” 操作时会抛出 Cancel 对象作为一场 * @class * @param {string=} message The message. */ function Cancel(message) { this.message = message; } Cancel.prototype.toString = function toString() { return this.message ? "Cancel: ".concat(this.message) : 'Cancel'; }; Cancel.prototype.__CANCEL__ = true; /** * 通过 CancelToken 来取消请求操作 * * @class * @param {Function} executor The executor function. */ function CancelToken(executor) { if (typeof executor !== 'function') { throw new TypeError('executor must be a function.'); } var resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); var token = this; executor(function cancel(message) { if (token.reason) { // 取消操作已被调用过 return; } token.reason = new Cancel(message); resolvePromise(token.reason); }); } /** * 如果请求已经取消,抛出 Cancel 异常 */ CancelToken.prototype.throwIfRequested = function throwIfRequested() { if (this.reason) { throw this.reason; } }; /** * 通过 source 来返回 CancelToken 实例和取消 CancelToken 的函数 */ CancelToken.source = function source() { var cancel; var token = new CancelToken(function executor(c) { cancel = c; }); return { token: token, cancel: cancel }; }; function isCancel(value) { return !!(value && value.__CANCEL__); } var request = function request() { var initOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var coreInstance = new Core(initOptions); var umiInstance = function umiInstance(url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var mergeOptions = objectSpread({}, initOptions, options, { headers: objectSpread({}, initOptions.headers, options.headers), params: objectSpread({}, getParamObject(initOptions.params), getParamObject(options.params)), method: (options.method || initOptions.method || 'get').toLowerCase() }); return coreInstance.request(url, mergeOptions); }; // 中间件 umiInstance.use = coreInstance.use.bind(coreInstance); umiInstance.fetchIndex = coreInstance.fetchIndex; // 拦截器 umiInstance.interceptors = { request: { use: Core.requestUse }, response: { use: Core.responseUse } }; // 请求语法糖: reguest.get request.post …… var METHODS = ['get', 'post', 'delete', 'put', 'patch', 'head', 'options', 'rpc']; METHODS.forEach(function (method) { umiInstance[method] = function (url, options) { return umiInstance(url, objectSpread({}, options, { method: method })); }; }); umiInstance.Cancel = Cancel; umiInstance.CancelToken = CancelToken; umiInstance.isCancel = isCancel; return umiInstance; }; /** * extend 方法参考了ky, 让用户可以定制配置. * initOpions 初始化参数 * @param {number} maxCache 最大缓存数 * @param {string} prefix url前缀 * @param {function} errorHandler 统一错误处理方法 * @param {object} headers 统一的headers */ var extend = function extend(initOptions) { return request(initOptions); }; /** * 暴露 fetch 中间件,保障依旧可以使用 */ var fetch$1 = request({ parseResponse: false }); var request$1 = request({}); export default request$1; export { Onion, RequestError, ResponseError, extend, fetch$1 as fetch };