UNPKG

@quickapp-eco/quickapp-axios

Version:

网络请求axios工具库在快应用平台上的实现

331 lines (280 loc) 10.4 kB
/*! * quick-app-fetch.js v0.1.0 * (c) 2020-2020 HeartCloud <ht1005cyh@163.com> * Released under the MIT License. */ import fetch$1 from '@system.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; var DEFAULT_CONTENT_TYPE = { 'Content-Type': 'application/x-www-form-urlencoded' }; var defaults = { transformResponse: [function transformResponse(data) { if (typeof data === 'string') { try { data = JSON.parse(data); } catch (e) {} } return data; }], validateCode: function validateCode(code) { return code >= 200 && code < 300; } }; defaults.header = { common: {} }; ['delete', 'get', 'head'].forEach(function (method) { defaults.header[method] = {}; }); ['post', 'put', 'patch'].forEach(function (method) { defaults.header[method] = Object.assign({}, DEFAULT_CONTENT_TYPE); }); function InterceptorManager() { this.handlers = []; } /** * Add a new interceptor to the stack * * @param {Function} fulfilled The function to handle `then` for a `Promise` * @param {Function} rejected The function to handle `reject` for a `Promise` * @return {Number} An ID used to remove interceptor later */ InterceptorManager.prototype.use = function use(fulfilled, rejected) { this.handlers.push({ fulfilled: fulfilled, rejected: rejected }); return this.handlers.length - 1; }; /** * Remove an interceptor from the stack * * @param {Number} id The ID that was returned by `use` */ InterceptorManager.prototype.eject = function eject(id) { if (this.handlers[id]) { this.handlers[id] = null; } }; /** * Iterate over all the registered interceptors * * @param {Function} fn The function to call for each interceptor */ InterceptorManager.prototype.forEach = function forEach(fn) { this.handlers.forEach(function (h) { if (h !== null) { fn(h); } }); }; /** * Update an Error with the specified config, error code, and response. * * @param {Error} error The error to update. * @param {Object} config The config. * @param {string} [code] The error code (for example, 'ECONNABORTED'). * @returns {Error} The error. */ function enhanceError(error, config, code) { error.config = config; if (code) { error.code = code; } return error; } /** * Create an Error with the specified message, config, error code, request and response. * * @param {string} message The error message. * @param {Object} config The config. * @param {string} [code] The error code (for example, 'ECONNABORTED'). * @returns {Error} The created error. */ function createError(message, config, code) { var error = new Error(message); return enhanceError(error, config, code); } /** * Resolve or reject a Promise based on response status. * * @param {Function} resolve A function that resolves the promise. * @param {Function} reject A function that rejects the promise. * @param {object} response The response. */ function settle(resolve, reject, response) { var validateCode = response.config.validateCode; if (!response.status || !validateCode || validateCode(response.status)) { resolve(response); } else { reject(createError('Request failed with status code ' + response.code, response.config, null)); } } /** * Execute a fetch request * * @param {object} config The config that is to be used for the request * @returns {Promise} The Promise to be fulfilled */ function http(config) { return new Promise(function (resolve, reject) { fetch$1.fetch(config).then(function (res) { var responseData = res.data; var response = { code: responseData.code, data: responseData.data, headers: responseData.headers, config: config }; settle(resolve, reject, response); })["catch"](function (error) { reject(createError(error.data, config, error.code)); }); }); } /** * Transform the data for a request or a response * * @param {Object|String} data The data to be transformed * @param {Array} headers The headers for the request or response * @param {Array|Function} fns A single function or Array of functions * @returns {*} The resulting transformed data */ function transformData(data, headers, fns) { fns.forEach(function (fn) { data = fn(data, headers); }); return data; } /** * Creates a new URL by combining the specified URLs * * @param {string} baseURL The base URL * @param {string} relativeURL The relative URL * @returns {string} The combined URL */ function combineURL(baseURL, relativeURL) { return relativeURL ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL; } /** * Determines whether the specified URL is absolute * * @param {string} url The URL to test * @returns {boolean} True if the specified URL is absolute, otherwise false */ function isAbsoluteURL(url) { return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); } /** * Dispatch a request to the server using the configured adapter * * @param {object} config The config that is to be used for the request * @returns {Promise} The Promise to be fulfilled */ function dispatchRequest(config) { if (config.baseURL && !isAbsoluteURL(config.url)) { config.url = combineURL(config.baseURL, config.url); } // Ensure header exist config.header = config.header || {}; // Flatten headers config.header = Object.assign({}, config.header.common || {}, config.header[config.method] || {}, config.header || {}); ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'].forEach(function (key) { delete config.header[key]; }); return http(config).then(function (response) { response.data = transformData(response.data, response.headers, config.transformResponse); return response; })["catch"](function (reason) { if (reason && reason.response) { reason.response.data = transformData(reason.response.data, reason.response.headers, config.transformResponse); } return Promise.reject(reason); }); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } /** * Create a new instance of Fetch * * @param {Object} instanceConfig The default config for the instance */ function Fetch(instanceConfig) { this.defaults = instanceConfig; this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager() }; } /** * Dispatch a request * * @param {Object} config The config specific for this request */ Fetch.prototype.request = function request(config) { config = Object.assign({}, defaults, { method: 'get' }, this.defaults, config); config.method = config.method.toLowerCase(); var chain = [dispatchRequest, undefined]; var promise = Promise.resolve(config); this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { chain.unshift(interceptor.fulfilled, interceptor.rejected); }); this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { chain.push(interceptor.fulfilled, interceptor.rejected); }); while (chain.length) { promise = promise.then(chain.shift(), chain.shift()); } return promise; }; // Provide aliases for supported request methods ['delete', 'get', 'head', 'options'].forEach(function (method) { Fetch.prototype[method] = function (url, config) { return this.request(_objectSpread({}, config || {}, { method: method, url: url })); }; }); ['post', 'put', 'patch'].forEach(function (method) { Fetch.prototype[method] = function (url, data, config) { return this.request(_objectSpread({}, config || {}, { method: method, url: url, data: data })); }; }); function ownKeys$1(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$1(Object(source), true).forEach(function (key) { defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$1(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } /** * Create an instance of Fetch * * @param {Object} defaultConfig The default config for the instance * @return {Fetch} A new instance of Fetch */ function createInstance(defaultConfig) { var context = new Fetch(defaultConfig); var instance = Fetch.prototype.request.bind(context); // Copy Fetch.prototype and context to instance Object.assign(instance, Fetch.prototype, context); return instance; } // Create the default instance to be exported var fetch = createInstance(defaults); // Expose Fetch class to allow class inheritance fetch.Fetch = Fetch; // Factory for creating new instances fetch.create = function create(instanceConfig) { return createInstance(_objectSpread$1({}, defaults, {}, instanceConfig)); }; export default fetch;