About the No Transport Error Solution Process for ajax requests in jquery in ie, jqueryajax
The first background is that the tester found that our webpage was incorrectly displayed in ie9. Actually, all asynchronous interfaces were not executed. Then I started the difficult troubleshooting process. All of our asynchronous interfaces are developed using jQuery's ajax method. The jquery version is 1.11.0.
I first found that the ajax method returned status = 0, statusText = No Transport. Then I started my journey of searching for problems. All the information I found on the Internet said this was caused by cross-origin.$.support.cros=true
You can. However, the actual interface accessed by our project does not belong to cross-origin. Therefore, although this attribute can solve the problem, the root cause is not found.
So I started to look at jquery's source code, first located the code segment with an error, and first pasted the error point:
1 // Get transport 2 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 3 4 // If no transport, we auto-abort 5 if ( !transport ) { 6 done( -1, "No Transport" ); 7 } else { 8 jqXHR.readyState = 1; 9 10 // Send global event11 if ( fireGlobals ) {12 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );13 }14 // Timeout15 if ( s.async && s.timeout > 0 ) {16 timeoutTimer = setTimeout(function() {17 jqXHR.abort("timeout");18 }, s.timeout );19 }20 21 try {22 state = 1;23 transport.send( requestHeaders, done );24 } catch ( e ) {25 // Propagate exception as error if not done26 if ( state < 2 ) {27 done( -1, e );28 // Simply rethrow otherwise29 } else {30 throw e;31 }32 }33 }
Transport = false. At the beginning, I couldn't fully understand the jquery source code. So I consulted a great God in our company. Under the guidance of a great god, I started to check why transport = false. After the omnipotent breakpoint debugging, it is found thatoptions.crossDomain = true
The key code that cannot enter this segment to correctly send the request (the specific code is not used for analysis ). At this point, I finally located the culprit, which was initially added to allow direct access to the api server on the html page.crossDomain=true
(Because the html and api server belong to different domain names ). (This is not over yet. Please proceed)
1 // Determine support properties 2 support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 3 xhrSupported = support.ajax = !!xhrSupported; 4 5 // Create transport if the browser can provide an xhr 6 if ( xhrSupported ) { 7 8 jQuery.ajaxTransport(function( options ) { 9 // Cross domain only allowed if supported through XMLHttpRequest 10 if ( !options.crossDomain || support.cors ) { 11 12 var callback; 13 14 return { 15 send: function( headers, complete ) { 16 var i, 17 xhr = options.xhr(), 18 id = ++xhrId; 19 20 // Open the socket 21 xhr.open( options.type, options.url, options.async, options.username, options.password ); 22 23 // Apply custom fields if provided 24 if ( options.xhrFields ) { 25 for ( i in options.xhrFields ) { 26 xhr[ i ] = options.xhrFields[ i ]; 27 } 28 } 29 30 // Override mime type if needed 31 if ( options.mimeType && xhr.overrideMimeType ) { 32 xhr.overrideMimeType( options.mimeType ); 33 } 34 35 // X-Requested-With header 36 // For cross-domain requests, seeing as conditions for a preflight are 37 // akin to a jigsaw puzzle, we simply never set it to be sure. 38 // (it can always be set on a per-request basis or even using ajaxSetup) 39 // For same-domain requests, won't change header if already provided. 40 if ( !options.crossDomain && !headers["X-Requested-With"] ) { 41 headers["X-Requested-With"] = "XMLHttpRequest"; 42 } 43 44 // Set headers 45 for ( i in headers ) { 46 // Support: IE<9 47 // IE's ActiveXObject throws a 'Type Mismatch' exception when setting 48 // request header to a null-value. 49 // 50 // To keep consistent with other XHR implementations, cast the value 51 // to string and ignore `undefined`. 52 if ( headers[ i ] !== undefined ) { 53 xhr.setRequestHeader( i, headers[ i ] + "" ); 54 } 55 } 56 57 // Do send the request 58 // This may raise an exception which is actually 59 // handled in jQuery.ajax (so no try/catch here) 60 xhr.send( ( options.hasContent && options.data ) || null ); 61 62 // Listener 63 callback = function( _, isAbort ) { 64 var status, statusText, responses; 65 66 // Was never called and is aborted or complete 67 if ( callback && ( isAbort || xhr.readyState === 4 ) ) { 68 // Clean up 69 delete xhrCallbacks[ id ]; 70 callback = undefined; 71 xhr.onreadystatechange = jQuery.noop; 72 73 // Abort manually if needed 74 if ( isAbort ) { 75 if ( xhr.readyState !== 4 ) { 76 xhr.abort(); 77 } 78 } else { 79 responses = {}; 80 status = xhr.status; 81 82 // Support: IE<10 83 // Accessing binary-data responseText throws an exception 84 // (#11426) 85 if ( typeof xhr.responseText === "string" ) { 86 responses.text = xhr.responseText; 87 } 88 89 // Firefox throws an exception when accessing 90 // statusText for faulty cross-domain requests 91 try { 92 statusText = xhr.statusText; 93 } catch( e ) { 94 // We normalize with Webkit giving an empty statusText 95 statusText = ""; 96 } 97 98 // Filter status for non standard behaviors 99 100 // If the request is local and we have data: assume a success101 // (success with no data won't get notified, that's the best we102 // can do given current implementations)103 if ( !status && options.isLocal && !options.crossDomain ) {104 status = responses.text ? 200 : 404;105 // IE - #1450: sometimes returns 1223 when it should be 204106 } else if ( status === 1223 ) {107 status = 204;108 }109 }110 }111 112 // Call complete if needed113 if ( responses ) {114 complete( status, statusText, responses, xhr.getAllResponseHeaders() );115 }116 };117 118 if ( !options.async ) {119 // if we're in sync mode we fire the callback120 callback();121 } else if ( xhr.readyState === 4 ) {122 // (IE6 & IE7) if it's in cache and has been123 // retrieved directly we need to fire the callback124 setTimeout( callback );125 } else {126 // Add to the list of active xhr callbacks127 xhr.onreadystatechange = xhrCallbacks[ id ] = callback;128 }129 },130 131 abort: function() {132 if ( callback ) {133 callback( undefined, true );134 }135 }136 };137 }138 });139 }
It should have ended, but it does not. Although I have addedcrossDomain=true
But why other browsers can access normally, but ie9 does not. I continue to debug the code, and finally found that the above Code in other browserssupport.cors = true
In ie9, this attribute is equal to false. From the code above, we can also see that the judgment of this attribute comes fromsupport.cors = !!xhrSupported && ( "withCredentials" in xhrSupported )
, WherexhrSupported= new window.XMLHttpRequest()
In ie9, XMLHttpRequest does not have the withCredentials attribute. That is to say, this problem is caused by the incompatibility of various browsers due to my misuse of attributes.