ajax.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // TODO: This file was created by bulk-decaffeinate.
  2. // Sanity-check the conversion and remove this comment.
  3. /*
  4. * decaffeinate suggestions:
  5. * DS102: Remove unnecessary code created because of implicit returns
  6. * DS205: Consider reworking code to avoid use of IIFEs
  7. * DS207: Consider shorter variations of null checks
  8. * DS208: Avoid top-level this
  9. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
  10. */
  11. const MIME_TYPES = {
  12. json: 'application/json',
  13. html: 'text/html'
  14. };
  15. this.ajax = function(options) {
  16. applyDefaults(options);
  17. serializeData(options);
  18. const xhr = new XMLHttpRequest();
  19. xhr.open(options.type, options.url, options.async);
  20. applyCallbacks(xhr, options);
  21. applyHeaders(xhr, options);
  22. xhr.send(options.data);
  23. if (options.async) {
  24. return {abort: abort.bind(undefined, xhr)};
  25. } else {
  26. return parseResponse(xhr, options);
  27. }
  28. };
  29. ajax.defaults = {
  30. async: true,
  31. dataType: 'json',
  32. timeout: 30,
  33. type: 'GET'
  34. };
  35. // contentType
  36. // context
  37. // data
  38. // error
  39. // headers
  40. // progress
  41. // success
  42. // url
  43. var applyDefaults = function(options) {
  44. for (var key in ajax.defaults) {
  45. if (options[key] == null) { options[key] = ajax.defaults[key]; }
  46. }
  47. };
  48. var serializeData = function(options) {
  49. if (!options.data) { return; }
  50. if (options.type === 'GET') {
  51. options.url += '?' + serializeParams(options.data);
  52. options.data = null;
  53. } else {
  54. options.data = serializeParams(options.data);
  55. }
  56. };
  57. var serializeParams = params => ((() => {
  58. const result = [];
  59. for (var key in params) {
  60. var value = params[key];
  61. result.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
  62. }
  63. return result;
  64. })()).join('&');
  65. var applyCallbacks = function(xhr, options) {
  66. if (!options.async) { return; }
  67. xhr.timer = setTimeout(onTimeout.bind(undefined, xhr, options), options.timeout * 1000);
  68. if (options.progress) { xhr.onprogress = options.progress; }
  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) { options.headers = {}; }
  78. if (options.contentType) {
  79. options.headers['Content-Type'] = options.contentType;
  80. }
  81. if (!options.headers['Content-Type'] && options.data && (options.type !== 'GET')) {
  82. options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
  83. }
  84. if (options.dataType) {
  85. options.headers['Accept'] = MIME_TYPES[options.dataType] || options.dataType;
  86. }
  87. for (var key in options.headers) {
  88. var value = options.headers[key];
  89. xhr.setRequestHeader(key, value);
  90. }
  91. };
  92. var onComplete = function(xhr, options) {
  93. if (200 <= xhr.status && xhr.status < 300) {
  94. let response;
  95. if ((response = parseResponse(xhr, options)) != null) {
  96. onSuccess(response, xhr, options);
  97. } else {
  98. onError('invalid', xhr, options);
  99. }
  100. } else {
  101. onError('error', xhr, options);
  102. }
  103. };
  104. var onSuccess = function(response, xhr, options) {
  105. if (options.success != null) {
  106. options.success.call(options.context, response, xhr, options);
  107. }
  108. };
  109. var onError = function(type, xhr, options) {
  110. if (options.error != null) {
  111. options.error.call(options.context, type, xhr, options);
  112. }
  113. };
  114. var onTimeout = function(xhr, options) {
  115. xhr.abort();
  116. onError('timeout', xhr, options);
  117. };
  118. var abort = function(xhr) {
  119. clearTimeout(xhr.timer);
  120. xhr.onreadystatechange = null;
  121. xhr.abort();
  122. };
  123. var parseResponse = function(xhr, options) {
  124. if (options.dataType === 'json') {
  125. return parseJSON(xhr.responseText);
  126. } else {
  127. return xhr.responseText;
  128. }
  129. };
  130. var parseJSON = function(json) {
  131. try { return JSON.parse(json); } catch (error) {}
  132. };