fly.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. (function webpackUniversalModuleDefinition(root, factory) {
  2. if(typeof exports === 'object' && typeof module === 'object')
  3. module.exports = factory();
  4. else if(typeof define === 'function' && define.amd)
  5. define([], factory);
  6. else {
  7. var a = factory();
  8. for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
  9. }
  10. })(this, function() {
  11. return /******/ (function(modules) { // webpackBootstrap
  12. /******/ // The module cache
  13. /******/ var installedModules = {};
  14. /******/
  15. /******/ // The require function
  16. /******/ function __webpack_require__(moduleId) {
  17. /******/
  18. /******/ // Check if module is in cache
  19. /******/ if(installedModules[moduleId]) {
  20. /******/ return installedModules[moduleId].exports;
  21. /******/ }
  22. /******/ // Create a new module (and put it into the cache)
  23. /******/ var module = installedModules[moduleId] = {
  24. /******/ i: moduleId,
  25. /******/ l: false,
  26. /******/ exports: {}
  27. /******/ };
  28. /******/
  29. /******/ // Execute the module function
  30. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  31. /******/
  32. /******/ // Flag the module as loaded
  33. /******/ module.l = true;
  34. /******/
  35. /******/ // Return the exports of the module
  36. /******/ return module.exports;
  37. /******/ }
  38. /******/
  39. /******/
  40. /******/ // expose the modules object (__webpack_modules__)
  41. /******/ __webpack_require__.m = modules;
  42. /******/
  43. /******/ // expose the module cache
  44. /******/ __webpack_require__.c = installedModules;
  45. /******/
  46. /******/ // identity function for calling harmony imports with the correct context
  47. /******/ __webpack_require__.i = function(value) { return value; };
  48. /******/
  49. /******/ // define getter function for harmony exports
  50. /******/ __webpack_require__.d = function(exports, name, getter) {
  51. /******/ if(!__webpack_require__.o(exports, name)) {
  52. /******/ Object.defineProperty(exports, name, {
  53. /******/ configurable: false,
  54. /******/ enumerable: true,
  55. /******/ get: getter
  56. /******/ });
  57. /******/ }
  58. /******/ };
  59. /******/
  60. /******/ // getDefaultExport function for compatibility with non-harmony modules
  61. /******/ __webpack_require__.n = function(module) {
  62. /******/ var getter = module && module.__esModule ?
  63. /******/ function getDefault() { return module['default']; } :
  64. /******/ function getModuleExports() { return module; };
  65. /******/ __webpack_require__.d(getter, 'a', getter);
  66. /******/ return getter;
  67. /******/ };
  68. /******/
  69. /******/ // Object.prototype.hasOwnProperty.call
  70. /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  71. /******/
  72. /******/ // __webpack_public_path__
  73. /******/ __webpack_require__.p = "";
  74. /******/
  75. /******/ // Load entry module and return exports
  76. /******/ return __webpack_require__(__webpack_require__.s = 2);
  77. /******/ })
  78. /************************************************************************/
  79. /******/ ([
  80. /* 0 */
  81. /***/ (function(module, exports, __webpack_require__) {
  82. "use strict";
  83. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  84. module.exports = {
  85. type: function type(ob) {
  86. return Object.prototype.toString.call(ob).slice(8, -1).toLowerCase();
  87. },
  88. isObject: function isObject(ob, real) {
  89. if (real) {
  90. return this.type(ob) === "object";
  91. } else {
  92. return ob && (typeof ob === 'undefined' ? 'undefined' : _typeof(ob)) === 'object';
  93. }
  94. },
  95. isFormData: function isFormData(val) {
  96. return typeof FormData !== 'undefined' && val instanceof FormData;
  97. },
  98. trim: function trim(str) {
  99. return str.replace(/(^\s*)|(\s*$)/g, '');
  100. },
  101. encode: function encode(val) {
  102. return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']');
  103. },
  104. formatParams: function formatParams(data) {
  105. var str = "";
  106. var first = true;
  107. var that = this;
  108. if (!this.isObject(data)) {
  109. return data;
  110. }
  111. function _encode(sub, path) {
  112. var encode = that.encode;
  113. var type = that.type(sub);
  114. if (type == "array") {
  115. sub.forEach(function (e, i) {
  116. if (!that.isObject(e)) i = "";
  117. _encode(e, path + ('%5B' + i + '%5D'));
  118. });
  119. } else if (type == "object") {
  120. for (var key in sub) {
  121. if (path) {
  122. _encode(sub[key], path + "%5B" + encode(key) + "%5D");
  123. } else {
  124. _encode(sub[key], encode(key));
  125. }
  126. }
  127. } else {
  128. if (!first) {
  129. str += "&";
  130. }
  131. first = false;
  132. str += path + "=" + encode(sub);
  133. }
  134. }
  135. _encode(data, "");
  136. return str;
  137. },
  138. // Do not overwrite existing attributes
  139. merge: function merge(a, b) {
  140. for (var key in b) {
  141. if (!a.hasOwnProperty(key)) {
  142. a[key] = b[key];
  143. } else if (this.isObject(b[key], 1) && this.isObject(a[key], 1)) {
  144. this.merge(a[key], b[key]);
  145. }
  146. }
  147. return a;
  148. }
  149. };
  150. /***/ }),
  151. /* 1 */,
  152. /* 2 */
  153. /***/ (function(module, exports, __webpack_require__) {
  154. function KEEP(_,cb){cb();}
  155. "use strict";
  156. var _createClass = function () { 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  157. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  158. var utils = __webpack_require__(0);
  159. var isBrowser = typeof document !== "undefined";
  160. var Fly = function () {
  161. function Fly(engine) {
  162. _classCallCheck(this, Fly);
  163. this.engine = engine || XMLHttpRequest;
  164. this.default = this; //For typeScript
  165. /**
  166. * Add lock/unlock API for interceptor.
  167. *
  168. * Once an request/response interceptor is locked, the incoming request/response
  169. * will be added to a queue before they enter the interceptor, they will not be
  170. * continued until the interceptor is unlocked.
  171. *
  172. * @param [interceptor] either is interceptors.request or interceptors.response
  173. */
  174. function wrap(interceptor) {
  175. var resolve = void 0;
  176. var reject = void 0;
  177. function _clear() {
  178. interceptor.p = resolve = reject = null;
  179. }
  180. utils.merge(interceptor, {
  181. lock: function lock() {
  182. if (!resolve) {
  183. interceptor.p = new Promise(function (_resolve, _reject) {
  184. resolve = _resolve;
  185. reject = _reject;
  186. });
  187. }
  188. },
  189. unlock: function unlock() {
  190. if (resolve) {
  191. resolve();
  192. _clear();
  193. }
  194. },
  195. clear: function clear() {
  196. if (reject) {
  197. reject("cancel");
  198. _clear();
  199. }
  200. }
  201. });
  202. }
  203. var interceptors = this.interceptors = {
  204. response: {
  205. use: function use(handler, onerror) {
  206. this.handler = handler;
  207. this.onerror = onerror;
  208. }
  209. },
  210. request: {
  211. use: function use(handler) {
  212. this.handler = handler;
  213. }
  214. }
  215. };
  216. var irq = interceptors.request;
  217. var irp = interceptors.response;
  218. wrap(irp);
  219. wrap(irq);
  220. this.config = {
  221. method: "GET",
  222. baseURL: "",
  223. headers: {},
  224. timeout: 0,
  225. params: {}, // Default Url params
  226. parseJson: true, // Convert response data to JSON object automatically.
  227. withCredentials: false
  228. };
  229. }
  230. _createClass(Fly, [{
  231. key: "request",
  232. value: function request(url, data, options) {
  233. var _this = this;
  234. var engine = new this.engine();
  235. var contentType = "Content-Type";
  236. var contentTypeLowerCase = contentType.toLowerCase();
  237. var interceptors = this.interceptors;
  238. var requestInterceptor = interceptors.request;
  239. var responseInterceptor = interceptors.response;
  240. var requestInterceptorHandler = requestInterceptor.handler;
  241. var promise = new Promise(function (resolve, reject) {
  242. if (utils.isObject(url)) {
  243. options = url;
  244. url = options.url;
  245. }
  246. options = options || {};
  247. options.headers = options.headers || {};
  248. function isPromise(p) {
  249. // some polyfill implementation of Promise may be not standard,
  250. // so, we test by duck-typing
  251. return p && p.then && p.catch;
  252. }
  253. /**
  254. * If the request/response interceptor has been locked,
  255. * the new request/response will enter a queue. otherwise, it will be performed directly.
  256. * @param [promise] if the promise exist, means the interceptor is locked.
  257. * @param [callback]
  258. */
  259. function enqueueIfLocked(promise, callback) {
  260. if (promise) {
  261. promise.then(function () {
  262. callback();
  263. });
  264. } else {
  265. callback();
  266. }
  267. }
  268. // make the http request
  269. function makeRequest(options) {
  270. data = options.body;
  271. // Normalize the request url
  272. url = utils.trim(options.url);
  273. var baseUrl = utils.trim(options.baseURL || "");
  274. if (!url && isBrowser && !baseUrl) url = location.href;
  275. if (url.indexOf("http") !== 0) {
  276. var isAbsolute = url[0] === "/";
  277. if (!baseUrl && isBrowser) {
  278. var arr = location.pathname.split("/");
  279. arr.pop();
  280. baseUrl = location.protocol + "//" + location.host + (isAbsolute ? "" : arr.join("/"));
  281. }
  282. if (baseUrl[baseUrl.length - 1] !== "/") {
  283. baseUrl += "/";
  284. }
  285. url = baseUrl + (isAbsolute ? url.substr(1) : url);
  286. if (isBrowser) {
  287. // Normalize the url which contains the ".." or ".", such as
  288. // "http://xx.com/aa/bb/../../xx" to "http://xx.com/xx" .
  289. var t = document.createElement("a");
  290. t.href = url;
  291. url = t.href;
  292. }
  293. }
  294. var responseType = utils.trim(options.responseType || "");
  295. var needQuery = ["GET", "HEAD", "DELETE", "OPTION"].indexOf(options.method) !== -1;
  296. var dataType = utils.type(data);
  297. var params = options.params || {};
  298. // merge url params when the method is "GET" (data is object)
  299. if (needQuery && dataType === "object") {
  300. params = utils.merge(data, params);
  301. }
  302. // encode params to String
  303. params = utils.formatParams(params);
  304. // save url params
  305. var _params = [];
  306. if (params) {
  307. _params.push(params);
  308. }
  309. // Add data to url params when the method is "GET" (data is String)
  310. if (needQuery && data && dataType === "string") {
  311. _params.push(data);
  312. }
  313. // make the final url
  314. if (_params.length > 0) {
  315. url += (url.indexOf("?") === -1 ? "?" : "&") + _params.join("&");
  316. }
  317. engine.open(options.method, url);
  318. // try catch for ie >=9
  319. try {
  320. engine.withCredentials = !!options.withCredentials;
  321. engine.timeout = options.timeout || 0;
  322. if (responseType !== "stream") {
  323. engine.responseType = responseType;
  324. }
  325. } catch (e) {}
  326. var customContentType = options.headers[contentType] || options.headers[contentTypeLowerCase];
  327. // default content type
  328. var _contentType = "application/x-www-form-urlencoded";
  329. // If the request data is json object, transforming it to json string,
  330. // and set request content-type to "json". In browser, the data will
  331. // be sent as RequestBody instead of FormData
  332. if (utils.trim((customContentType || "").toLowerCase()) === _contentType) {
  333. data = utils.formatParams(data);
  334. } else if (!utils.isFormData(data) && ["object", "array"].indexOf(utils.type(data)) !== -1) {
  335. _contentType = 'application/json;charset=utf-8';
  336. data = JSON.stringify(data);
  337. }
  338. //If user doesn't set content-type, set default.
  339. if (!(customContentType || needQuery)) {
  340. options.headers[contentType] = _contentType;
  341. }
  342. for (var k in options.headers) {
  343. if (k === contentType && utils.isFormData(data)) {
  344. // Delete the content-type, Let the browser set it
  345. delete options.headers[k];
  346. } else {
  347. try {
  348. // In browser environment, some header fields are readonly,
  349. // write will cause the exception .
  350. engine.setRequestHeader(k, options.headers[k]);
  351. } catch (e) {}
  352. }
  353. }
  354. function onresult(handler, data, type) {
  355. enqueueIfLocked(responseInterceptor.p, function () {
  356. if (handler) {
  357. //如果失败,添加请求信息
  358. if (type) {
  359. data.request = options;
  360. }
  361. var ret = handler.call(responseInterceptor, data, Promise);
  362. data = ret === undefined ? data : ret;
  363. }
  364. if (!isPromise(data)) {
  365. data = Promise[type === 0 ? "resolve" : "reject"](data);
  366. }
  367. data.then(function (d) {
  368. resolve(d);
  369. }).catch(function (e) {
  370. reject(e);
  371. });
  372. });
  373. }
  374. function onerror(e) {
  375. e.engine = engine;
  376. onresult(responseInterceptor.onerror, e, -1);
  377. }
  378. function Err(msg, status) {
  379. this.message = msg;
  380. this.status = status;
  381. }
  382. engine.onload = function () {
  383. try {
  384. // The xhr of IE9 has not response field
  385. var response = engine.response || engine.responseText;
  386. if (response && options.parseJson && (engine.getResponseHeader(contentType) || "").indexOf("json") !== -1
  387. // Some third engine implementation may transform the response text to json object automatically,
  388. // so we should test the type of response before transforming it
  389. && !utils.isObject(response)) {
  390. response = JSON.parse(response);
  391. }
  392. var headers = engine.responseHeaders;
  393. // In browser
  394. if (!headers) {
  395. headers = {};
  396. var items = (engine.getAllResponseHeaders() || "").split("\r\n");
  397. items.pop();
  398. items.forEach(function (e) {
  399. if (!e) return;
  400. var key = e.split(":")[0];
  401. headers[key] = engine.getResponseHeader(key);
  402. });
  403. }
  404. var status = engine.status;
  405. var statusText = engine.statusText;
  406. var _data = { data: response, headers: headers, status: status, statusText: statusText };
  407. // The _response filed of engine is set in adapter which be called in engine-wrapper.js
  408. utils.merge(_data, engine._response);
  409. if (status >= 200 && status < 300 || status === 304) {
  410. _data.engine = engine;
  411. _data.request = options;
  412. onresult(responseInterceptor.handler, _data, 0);
  413. } else {
  414. var e = new Err(statusText, status);
  415. e.response = _data;
  416. onerror(e);
  417. }
  418. } catch (e) {
  419. onerror(new Err(e.msg, engine.status));
  420. }
  421. };
  422. engine.onerror = function (e) {
  423. onerror(new Err(e.msg || "Network Error", 0));
  424. };
  425. engine.ontimeout = function () {
  426. onerror(new Err("timeout [ " + engine.timeout + "ms ]", 1));
  427. };
  428. engine._options = options;
  429. setTimeout(function () {
  430. engine.send(needQuery ? null : data);
  431. }, 0);
  432. }
  433. enqueueIfLocked(requestInterceptor.p, function () {
  434. utils.merge(options, JSON.parse(JSON.stringify(_this.config)));
  435. var headers = options.headers;
  436. headers[contentType] = headers[contentType] || headers[contentTypeLowerCase] || "";
  437. delete headers[contentTypeLowerCase];
  438. options.body = data || options.body;
  439. url = utils.trim(url || "");
  440. options.method = options.method.toUpperCase();
  441. options.url = url;
  442. var ret = options;
  443. if (requestInterceptorHandler) {
  444. ret = requestInterceptorHandler.call(requestInterceptor, options, Promise) || options;
  445. }
  446. if (!isPromise(ret)) {
  447. ret = Promise.resolve(ret);
  448. }
  449. ret.then(function (d) {
  450. //if options continue
  451. if (d === options) {
  452. makeRequest(d);
  453. } else {
  454. resolve(d);
  455. }
  456. }, function (err) {
  457. reject(err);
  458. });
  459. });
  460. });
  461. promise.engine = engine;
  462. return promise;
  463. }
  464. }, {
  465. key: "all",
  466. value: function all(promises) {
  467. return Promise.all(promises);
  468. }
  469. }, {
  470. key: "spread",
  471. value: function spread(callback) {
  472. return function (arr) {
  473. return callback.apply(null, arr);
  474. };
  475. }
  476. }]);
  477. return Fly;
  478. }();
  479. //For typeScript
  480. Fly.default = Fly;
  481. ["get", "post", "put", "patch", "head", "delete"].forEach(function (e) {
  482. Fly.prototype[e] = function (url, data, option) {
  483. return this.request(url, data, utils.merge({ method: e }, option));
  484. };
  485. });
  486. ["lock", "unlock", "clear"].forEach(function (e) {
  487. Fly.prototype[e] = function () {
  488. this.interceptors.request[e]();
  489. };
  490. });
  491. // Learn more about keep-loader: https://github.com/wendux/keep-loader
  492. ;
  493. module.exports = Fly;
  494. /***/ })
  495. /******/ ]);
  496. });