xhr.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. define( [
  2. "../core",
  3. "../var/support",
  4. "../ajax"
  5. ], function( jQuery, support ) {
  6. "use strict";
  7. jQuery.ajaxSettings.xhr = function() {
  8. try {
  9. return new window.XMLHttpRequest();
  10. } catch ( e ) {}
  11. };
  12. var xhrSuccessStatus = {
  13. // File protocol always yields status code 0, assume 200
  14. 0: 200,
  15. // Support: IE <=9 only
  16. // #1450: sometimes IE returns 1223 when it should be 204
  17. 1223: 204
  18. },
  19. xhrSupported = jQuery.ajaxSettings.xhr();
  20. support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
  21. support.ajax = xhrSupported = !!xhrSupported;
  22. jQuery.ajaxTransport( function( options ) {
  23. var callback, errorCallback;
  24. // Cross domain only allowed if supported through XMLHttpRequest
  25. if ( support.cors || xhrSupported && !options.crossDomain ) {
  26. return {
  27. send: function( headers, complete ) {
  28. var i,
  29. xhr = options.xhr();
  30. xhr.open(
  31. options.type,
  32. options.url,
  33. options.async,
  34. options.username,
  35. options.password
  36. );
  37. // Apply custom fields if provided
  38. if ( options.xhrFields ) {
  39. for ( i in options.xhrFields ) {
  40. xhr[ i ] = options.xhrFields[ i ];
  41. }
  42. }
  43. // Override mime type if needed
  44. if ( options.mimeType && xhr.overrideMimeType ) {
  45. xhr.overrideMimeType( options.mimeType );
  46. }
  47. // X-Requested-With header
  48. // For cross-domain requests, seeing as conditions for a preflight are
  49. // akin to a jigsaw puzzle, we simply never set it to be sure.
  50. // (it can always be set on a per-request basis or even using ajaxSetup)
  51. // For same-domain requests, won't change header if already provided.
  52. if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
  53. headers[ "X-Requested-With" ] = "XMLHttpRequest";
  54. }
  55. // Set headers
  56. for ( i in headers ) {
  57. xhr.setRequestHeader( i, headers[ i ] );
  58. }
  59. // Callback
  60. callback = function( type ) {
  61. return function() {
  62. if ( callback ) {
  63. callback = errorCallback = xhr.onload =
  64. xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
  65. if ( type === "abort" ) {
  66. xhr.abort();
  67. } else if ( type === "error" ) {
  68. // Support: IE <=9 only
  69. // On a manual native abort, IE9 throws
  70. // errors on any property access that is not readyState
  71. if ( typeof xhr.status !== "number" ) {
  72. complete( 0, "error" );
  73. } else {
  74. complete(
  75. // File: protocol always yields status 0; see #8605, #14207
  76. xhr.status,
  77. xhr.statusText
  78. );
  79. }
  80. } else {
  81. complete(
  82. xhrSuccessStatus[ xhr.status ] || xhr.status,
  83. xhr.statusText,
  84. // Support: IE <=9 only
  85. // IE9 has no XHR2 but throws on binary (trac-11426)
  86. // For XHR2 non-text, let the caller handle it (gh-2498)
  87. ( xhr.responseType || "text" ) !== "text" ||
  88. typeof xhr.responseText !== "string" ?
  89. { binary: xhr.response } :
  90. { text: xhr.responseText },
  91. xhr.getAllResponseHeaders()
  92. );
  93. }
  94. }
  95. };
  96. };
  97. // Listen to events
  98. xhr.onload = callback();
  99. errorCallback = xhr.onerror = callback( "error" );
  100. // Support: IE 9 only
  101. // Use onreadystatechange to replace onabort
  102. // to handle uncaught aborts
  103. if ( xhr.onabort !== undefined ) {
  104. xhr.onabort = errorCallback;
  105. } else {
  106. xhr.onreadystatechange = function() {
  107. // Check readyState before timeout as it changes
  108. if ( xhr.readyState === 4 ) {
  109. // Allow onerror to be called first,
  110. // but that will not handle a native abort
  111. // Also, save errorCallback to a variable
  112. // as xhr.onerror cannot be accessed
  113. window.setTimeout( function() {
  114. if ( callback ) {
  115. errorCallback();
  116. }
  117. } );
  118. }
  119. };
  120. }
  121. // Create the abort callback
  122. callback = callback( "abort" );
  123. try {
  124. // Do send the request (this may raise an exception)
  125. xhr.send( options.hasContent && options.data || null );
  126. } catch ( e ) {
  127. // #14683: Only rethrow if this hasn't been notified as an error yet
  128. if ( callback ) {
  129. throw e;
  130. }
  131. }
  132. },
  133. abort: function() {
  134. if ( callback ) {
  135. callback();
  136. }
  137. }
  138. };
  139. }
  140. } );
  141. } );