xhr.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. define([
  2. "../core",
  3. "../var/support",
  4. "../ajax"
  5. ], function( jQuery, support ) {
  6. jQuery.ajaxSettings.xhr = function() {
  7. try {
  8. return new XMLHttpRequest();
  9. } catch( e ) {}
  10. };
  11. var xhrId = 0,
  12. xhrCallbacks = {},
  13. xhrSuccessStatus = {
  14. // file protocol always yields status code 0, assume 200
  15. 0: 200,
  16. // Support: IE9
  17. // #1450: sometimes IE returns 1223 when it should be 204
  18. 1223: 204
  19. },
  20. xhrSupported = jQuery.ajaxSettings.xhr();
  21. // Support: IE9
  22. // Open requests must be manually aborted on unload (#5280)
  23. // See https://support.microsoft.com/kb/2856746 for more info
  24. if ( window.attachEvent ) {
  25. window.attachEvent( "onunload", function() {
  26. for ( var key in xhrCallbacks ) {
  27. xhrCallbacks[ key ]();
  28. }
  29. });
  30. }
  31. support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
  32. support.ajax = xhrSupported = !!xhrSupported;
  33. jQuery.ajaxTransport(function( options ) {
  34. var callback;
  35. // Cross domain only allowed if supported through XMLHttpRequest
  36. if ( support.cors || xhrSupported && !options.crossDomain ) {
  37. return {
  38. send: function( headers, complete ) {
  39. var i,
  40. xhr = options.xhr(),
  41. id = ++xhrId;
  42. xhr.open( options.type, options.url, options.async, options.username, options.password );
  43. // Apply custom fields if provided
  44. if ( options.xhrFields ) {
  45. for ( i in options.xhrFields ) {
  46. xhr[ i ] = options.xhrFields[ i ];
  47. }
  48. }
  49. // Override mime type if needed
  50. if ( options.mimeType && xhr.overrideMimeType ) {
  51. xhr.overrideMimeType( options.mimeType );
  52. }
  53. // X-Requested-With header
  54. // For cross-domain requests, seeing as conditions for a preflight are
  55. // akin to a jigsaw puzzle, we simply never set it to be sure.
  56. // (it can always be set on a per-request basis or even using ajaxSetup)
  57. // For same-domain requests, won't change header if already provided.
  58. if ( !options.crossDomain && !headers["X-Requested-With"] ) {
  59. headers["X-Requested-With"] = "XMLHttpRequest";
  60. }
  61. // Set headers
  62. for ( i in headers ) {
  63. xhr.setRequestHeader( i, headers[ i ] );
  64. }
  65. // Callback
  66. callback = function( type ) {
  67. return function() {
  68. if ( callback ) {
  69. delete xhrCallbacks[ id ];
  70. callback = xhr.onload = xhr.onerror = null;
  71. if ( type === "abort" ) {
  72. xhr.abort();
  73. } else if ( type === "error" ) {
  74. complete(
  75. // file: protocol always yields status 0; see #8605, #14207
  76. xhr.status,
  77. xhr.statusText
  78. );
  79. } else {
  80. complete(
  81. xhrSuccessStatus[ xhr.status ] || xhr.status,
  82. xhr.statusText,
  83. // Support: IE9
  84. // Accessing binary-data responseText throws an exception
  85. // (#11426)
  86. typeof xhr.responseText === "string" ? {
  87. text: xhr.responseText
  88. } : undefined,
  89. xhr.getAllResponseHeaders()
  90. );
  91. }
  92. }
  93. };
  94. };
  95. // Listen to events
  96. xhr.onload = callback();
  97. xhr.onerror = callback("error");
  98. // Create the abort callback
  99. callback = xhrCallbacks[ id ] = callback("abort");
  100. try {
  101. // Do send the request (this may raise an exception)
  102. xhr.send( options.hasContent && options.data || null );
  103. } catch ( e ) {
  104. // #14683: Only rethrow if this hasn't been notified as an error yet
  105. if ( callback ) {
  106. throw e;
  107. }
  108. }
  109. },
  110. abort: function() {
  111. if ( callback ) {
  112. callback();
  113. }
  114. }
  115. };
  116. }
  117. });
  118. });