xhr.js 4.2 KB

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