关于jquery中ajax请求在ie中报No Transport错误解决流程

首先背景就是测试同学发现我们的网页在ie9中展示不正确,实际是所有异步的接口都没有执行。然后我就开始了苦逼的排查过程。我们所有异步接口都是使用jQuery的ajax方法发出的,使用的jquery版本是1.11.0。

我最先定位到的是ajax方法返回status=0,statusText=No Transport。然后开始了我的查找问题之旅,我在网上所查出的资料都说这个是由于跨域造成的,加上$.support.cros=true就可以。但实际我们项目访问的接口并不属于跨域。所以虽然加上这个属性可以解决问题,但并没有找到根源。

于是我开始看jquery的源码,先定位了发生错误的代码段,先贴上报错点:

 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 event
11             if ( fireGlobals ) {
12                 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
13             }
14             // Timeout
15             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 done
26                 if ( state < 2 ) {
27                     done( -1, e );
28                 // Simply rethrow otherwise
29                 } else {
30                     throw e;
31                 }
32             }
33         }

 

此处transport =false。刚开始并不能完全看懂jquery源码,于是请教了我们公司的一位大神,在大神的指导下我开始排查为何transport =false。经过万能的断点调试,发现是由于下列代码中的options.crossDomain = true导致的不能进入此段正确发送请求的关键代码(具体的代码作用不作分析)。到此终于定位罪魁祸首是最初我为了在html页面可以直接访问api服务器而增加的crossDomain=true的设置(因为html和api服务器属于不同域名)。(此处并未结束,请继续往下看)

  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 success
101                                 // (success with no data won't get notified, that's the best we
102                                 // 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 204
106                                 } else if ( status === 1223 ) {
107                                     status = 204;
108                                 }
109                             }
110                         }
111 
112                         // Call complete if needed
113                         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 callback
120                         callback();
121                     } else if ( xhr.readyState === 4 ) {
122                         // (IE6 & IE7) if it's in cache and has been
123                         // retrieved directly we need to fire the callback
124                         setTimeout( callback );
125                     } else {
126                         // Add to the list of active xhr callbacks
127                         xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
128                     }
129                 },
130 
131                 abort: function() {
132                     if ( callback ) {
133                         callback( undefined, true );
134                     }
135                 }
136             };
137         }
138     });
139 }

 

到此本来应该结束了,但并没有,虽然我增加了crossDomain=true的设置,但为何其他浏览器可以正常访问,而ie9不行呢。我继续调试代码,最终发现其他浏览器上述代码中support.cors = true,而ie9下这个属性等于false。从上述代码中也可以看到,这个属性的判断来自于support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ),其中xhrSupported= new window.XMLHttpRequest(),ie9中XMLHttpRequest没有withCredentials属性。也就是说这个问题是由于我的乱用属性加上各浏览器兼容性问题而导致的。

转载于:https://www.cnblogs.com/blanche91/p/6825861.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值