ajax.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. const MIME_TYPES = {
  2. json: "application/json",
  3. html: "text/html",
  4. };
  5. function ajax(options) {
  6. applyDefaults(options);
  7. serializeData(options);
  8. const xhr = new XMLHttpRequest();
  9. xhr.open(options.type, options.url, options.async);
  10. applyCallbacks(xhr, options);
  11. applyHeaders(xhr, options);
  12. xhr.send(options.data);
  13. if (options.async) {
  14. return { abort: abort.bind(undefined, xhr) };
  15. } else {
  16. return parseResponse(xhr, options);
  17. }
  18. }
  19. ajax.defaults = {
  20. async: true,
  21. dataType: "json",
  22. timeout: 30,
  23. type: "GET",
  24. };
  25. // contentType
  26. // context
  27. // data
  28. // error
  29. // headers
  30. // progress
  31. // success
  32. // url
  33. var applyDefaults = function (options) {
  34. for (var key in ajax.defaults) {
  35. if (options[key] == null) {
  36. options[key] = ajax.defaults[key];
  37. }
  38. }
  39. };
  40. var serializeData = function (options) {
  41. if (!options.data) {
  42. return;
  43. }
  44. if (options.type === "GET") {
  45. options.url += "?" + serializeParams(options.data);
  46. options.data = null;
  47. } else {
  48. options.data = serializeParams(options.data);
  49. }
  50. };
  51. var serializeParams = (params) =>
  52. Object.entries(params)
  53. .map(
  54. ([key, value]) =>
  55. `${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
  56. )
  57. .join("&");
  58. var applyCallbacks = function (xhr, options) {
  59. if (!options.async) {
  60. return;
  61. }
  62. xhr.timer = setTimeout(
  63. onTimeout.bind(undefined, xhr, options),
  64. options.timeout * 1000,
  65. );
  66. if (options.progress) {
  67. xhr.onprogress = options.progress;
  68. }
  69. xhr.onreadystatechange = function () {
  70. if (xhr.readyState === 4) {
  71. clearTimeout(xhr.timer);
  72. onComplete(xhr, options);
  73. }
  74. };
  75. };
  76. var applyHeaders = function (xhr, options) {
  77. if (!options.headers) {
  78. options.headers = {};
  79. }
  80. if (options.contentType) {
  81. options.headers["Content-Type"] = options.contentType;
  82. }
  83. if (
  84. !options.headers["Content-Type"] &&
  85. options.data &&
  86. options.type !== "GET"
  87. ) {
  88. options.headers["Content-Type"] = "application/x-www-form-urlencoded";
  89. }
  90. if (options.dataType) {
  91. options.headers["Accept"] =
  92. MIME_TYPES[options.dataType] || options.dataType;
  93. }
  94. for (var key in options.headers) {
  95. var value = options.headers[key];
  96. xhr.setRequestHeader(key, value);
  97. }
  98. };
  99. var onComplete = function (xhr, options) {
  100. if (200 <= xhr.status && xhr.status < 300) {
  101. let response;
  102. if ((response = parseResponse(xhr, options)) != null) {
  103. onSuccess(response, xhr, options);
  104. } else {
  105. onError("invalid", xhr, options);
  106. }
  107. } else {
  108. onError("error", xhr, options);
  109. }
  110. };
  111. var onSuccess = function (response, xhr, options) {
  112. if (options.success != null) {
  113. options.success.call(options.context, response, xhr, options);
  114. }
  115. };
  116. var onError = function (type, xhr, options) {
  117. if (options.error != null) {
  118. options.error.call(options.context, type, xhr, options);
  119. }
  120. };
  121. var onTimeout = function (xhr, options) {
  122. xhr.abort();
  123. onError("timeout", xhr, options);
  124. };
  125. var abort = function (xhr) {
  126. clearTimeout(xhr.timer);
  127. xhr.onreadystatechange = null;
  128. xhr.abort();
  129. };
  130. var parseResponse = function (xhr, options) {
  131. if (options.dataType === "json") {
  132. return parseJSON(xhr.responseText);
  133. } else {
  134. return xhr.responseText;
  135. }
  136. };
  137. var parseJSON = function (json) {
  138. try {
  139. return JSON.parse(json);
  140. } catch (error) {}
  141. };