标签:
var xhr=new XMLHttpRequest();xhr.onreadystatechange=function(e){console.log(e);if(xhr.readyState==4 && xhr.status==200){console.log(xhr);console.log(xhr.responseText);}}xhr.open(‘get‘,‘./data.json‘);xhr.send();


response中已经有了数据,响应内容默认为字符串
responseType为‘‘,也就是默认值
responseText中是响应主体的内容
responseURL指出了我们请求的资源路径
上图中的信息:responseType是一个空字符串,也就是指明了返回的是一个字符串,而且从下面的log我们也可以看出来,为了清楚,我把xhr.responseText的类型也打印了出来,确实是string。
而如果我们换成下面的代码:
var xhr=$.ajax({url:‘./data.json‘,success:function(data){console.log(data);}});console.log(xhr);
得到结果截图如下:

这个被jQuery改的面目全非的xmlhttprequest对象,先看一个左侧的属性,其中有一个responseJSON,这是jquery的实现,标准中是没有这个属性的,而它的responseText是字符串。所以success回调应该就是调的这个属性咯。看下请求,没有什么区别:Content-Type都是application/json ,其实我们再切到response标签看下,是一样的数据格式。所以是不是可以说原生获取json格式数据的话,值都是json字符串形式的值?
这里的jquery版本为1.11.2,查看源码可以发现:在ajax方法中定义的done方法内,有这么一句:
// Get response data 这里是得到相应的内容,本例就是"‘{"username":"ruby","age":"18"}‘"if ( responses ) {response = ajaxHandleResponses( s, jqXHR, responses );}// Convert no matter what (that way responseXXX fields are always set)response = ajaxConvert( s, response, jqXHR, isSuccess );
也就是说,在得到最终请求数据时,jquery会去做响应内容的自动转换,先来看ajaxHandleResponses方法,它用于返回响应内容:
function ajaxHandleResponses( s, jqXHR, responses ) {var firstDataType, ct, finalDataType, type,contents = s.contents,dataTypes = s.dataTypes;// Remove auto dataType and get content-type in the processwhile ( dataTypes[ 0 ] === "*" ) {dataTypes.shift();if ( ct === undefined ) {ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");/*这里的s是使用ajax传入的参数转化而来的对象,用于存储前端开发人员发起该请求时对请求的一些设置和js默认对请求的设置,s.mimeType是使用overrideMIMEType时会被写入s的,其实也就是在ajax方法中我们指定的contentType,如果没有该属性,就是查找相应对象的Content-Type属性,而这个是肯定有值的,本例中ct=‘application/json‘,即获取到了响应报文中报头Content-Type的值*/}}// Check if we‘re dealing with a known content-typeif ( ct ) {for ( type in contents ) {/*contents是一个固定的对象,用于匹配各种类型的数据{html: /html/json: /json/script: /(?:java|ecma)script/xml: /xml/}*/if ( contents[ type ] && contents[ type ].test( ct ) ) {dataTypes.unshift( type );/*这里我们显然是匹配到了json这一项,所以dataTypes中加上一项[‘json‘]*/break;}}}// Check to see if we have a response for the expected dataTypeif ( dataTypes[ 0 ] in responses ) {finalDataType = dataTypes[ 0 ];//如果这个类型的数据在responses中正好有,那么就直接将最终类型定义为dataType中的这一项,本例中,dataTypes[0]为‘json‘,但实际返回的响应是text。responses就是根据相应内容生成的响应对象,这里是"{text:"{"username":"ruby","age":"18"}"}".} else {// Try convertible dataTypesfor ( type in responses ) {if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {//检测responses中的各个类型的值是否可以转换为我们想得到的类型, 本例中这里的type为‘text‘,s.converters定义的是各种转换用到的函数,比如s.converters[‘text json‘]=JSON.parse。本例中这里是可以转换的。/*还是列出来吧:s.converters:{"text script": function( text ) {jQuery.globalEval( text );return text;},// Convert anything to text"* text": String,// Text to html (true = no transformation)"text html": true,// Evaluate text as a json expression"text json": jQuery.parseJSON,// Parse text as xml"text xml": jQuery.parseXML}*/finalDataType = type;break;}if ( !firstDataType ) {firstDataType = type;}}// Or just use first onefinalDataType = finalDataType || firstDataType;}// If we found a dataType// We add the dataType to the list if needed// and return the corresponding responseif ( finalDataType ) {if ( finalDataType !== dataTypes[ 0 ] ) {dataTypes.unshift( finalDataType );//完善s.dataTypes中的值,即完善响应数据的类型,此时为[‘text‘,‘json‘]}return responses[ finalDataType ];//最终返回responses[‘text‘]}}
再来看ajaxConvert方法:
/* Chain conversions given the request and the original response* Also sets the responseXXX fields on the jqXHR instance*/function ajaxConvert( s, response, jqXHR, isSuccess ) {var conv2, current, conv, tmp, prev,converters = {},// Work with a copy of dataTypes in case we need to modify it for conversiondataTypes = s.dataTypes.slice();//数组copy这么写?不知道为啥~你知道的话还望不吝赐教~// Create converters map with lowercased keysif ( dataTypes[ 1 ] ) {for ( conv in s.converters ) {converters[ conv.toLowerCase() ] = s.converters[ conv ];//构造一个转换对象,内容是s.converters中的那些转换函数.}}current = dataTypes.shift();// Convert to each sequential dataTypewhile ( current ) {if ( s.responseFields[ current ] ) {jqXHR[ s.responseFields[ current ] ] = response;//这里给jqXHR即jquery构造出来的XMLHttpRequest对象赋值,在本例中,它在此添加了两个属性,一个是responseText,一个是responseJson}// Apply the dataFilter if providedif ( !prev && isSuccess && s.dataFilter ) {response = s.dataFilter( response, s.dataType );}prev = current;current = dataTypes.shift();//记住第一个类型,再获取第二个类型,这里的prev为‘text’, current为‘json‘。if ( current ) {// There‘s only work to do if current dataType is non-autoif ( current === "*" ) {current = prev;// Convert response if prev dataType is non-auto and differs from current} else if ( prev !== "*" && prev !== current ) {// Seek a direct converterconv = converters[ prev + " " + current ] || converters[ "* " + current ];//看看是否有prev类转current类的转换方法// If none found, seek a pairif ( !conv ) {for ( conv2 in converters ) {// If conv2 outputs currenttmp = conv2.split( " " );if ( tmp[ 1 ] === current ) {// If prev can be converted to accepted inputconv = converters[ prev + " " + tmp[ 0 ] ] ||converters[ "* " + tmp[ 0 ] ];if ( conv ) {// Condense equivalence convertersif ( conv === true ) {conv = converters[ conv2 ];// Otherwise, insert the intermediate dataType} else if ( converters[ conv2 ] !== true ) {current = tmp[ 0 ];dataTypes.unshift( tmp[ 1 ] );}break;}}}}// Apply converter (if not an equivalence)if ( conv !== true ) {// Unless errors are allowed to bubble, catch and return themif ( conv && s[ "throws" ] ) {response = conv( response );} else {try {response = conv( response );//转换为我们想要的数据类型,截至此我们已经得到想要的json数据啦} catch ( e ) {return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };}}}}}}return { state: "success", data: response };}
上面基本根据当前案例进行代码解析,很多情况没有一一列出,感兴趣的童鞋可以通过打断点调试的方式来解析代码。
标签:
原文地址:http://www.cnblogs.com/rubyisaPM/p/4412897.html