jquery的http请求对响应内容的处理

写在前面:在学习XMLHttpRequest对象时碰到的一个问题,发现jquery的http请求会自动处理响应内容,变为开发者想要的数据,下面来看看吧:

实验案例:

  1. var xhr=new XMLHttpRequest();
  2. xhr.onreadystatechange=function(e){
  3. console.log(e);
  4. if(xhr.readyState==4 && xhr.status==200){
  5. console.log(xhr);
  6. console.log(xhr.responseText);
  7. }
  8. }
  9. xhr.open(‘get‘,‘./data.json‘);
  10. xhr.send();

请求成功后的xhr:

response中已经有了数据,响应内容默认为字符串
responseType为‘‘,也就是默认值
responseText中是响应主体的内容
responseURL指出了我们请求的资源路径

为什么返回的不是json对象?

上图中的信息:responseType是一个空字符串,也就是指明了返回的是一个字符串,而且从下面的log我们也可以看出来,为了清楚,我把xhr.responseText的类型也打印了出来,确实是string。
而如果我们换成下面的代码:

  1. var xhr=$.ajax({
  2. url:‘./data.json‘,
  3. success:function(data){
  4. console.log(data);
  5. }
  6. });
  7. console.log(xhr);

得到结果截图如下:

这个被jQuery改的面目全非的xmlhttprequest对象,先看一个左侧的属性,其中有一个responseJSON,这是jquery的实现,标准中是没有这个属性的,而它的responseText是字符串。所以success回调应该就是调的这个属性咯。看下请求,没有什么区别:Content-Type都是application/json ,其实我们再切到response标签看下,是一样的数据格式。所以是不是可以说原生获取json格式数据的话,值都是json字符串形式的值?

这里的jquery版本为1.11.2,查看源码可以发现:在ajax方法中定义的done方法内,有这么一句:

  1. // Get response data 这里是得到相应的内容,本例就是"‘{"username":"ruby","age":"18"}‘"
  2. if ( responses ) {
  3. response = ajaxHandleResponses( s, jqXHR, responses );
  4. }
  5. // Convert no matter what (that way responseXXX fields are always set)
  6. response = ajaxConvert( s, response, jqXHR, isSuccess );

也就是说,在得到最终请求数据时,jquery会去做响应内容的自动转换,先来看ajaxHandleResponses方法,它用于返回响应内容:

  1. function ajaxHandleResponses( s, jqXHR, responses ) {
  2. var firstDataType, ct, finalDataType, type,
  3. contents = s.contents,
  4. dataTypes = s.dataTypes;
  5. // Remove auto dataType and get content-type in the process
  6. while ( dataTypes[ 0 ] === "*" ) {
  7. dataTypes.shift();
  8. if ( ct === undefined ) {
  9. ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
  10. /*这里的s是使用ajax传入的参数转化而来的对象,用于存储前端开发人员发起该请求时对请求的一些设置和js默认对请求的设置,
  11. s.mimeType是使用overrideMIMEType时会被写入s的,其实也就是在ajax方法中我们指定的contentType,如果没有该属性,
  12. 就是查找相应对象的Content-Type属性,而这个是肯定有值的,本例中ct=‘application/json‘,即获取到了响应报文中报头Content-Type的值*/
  13. }
  14. }
  15. // Check if we‘re dealing with a known content-type
  16. if ( ct ) {
  17. for ( type in contents ) {
  18. /*
  19. contents是一个固定的对象,用于匹配各种类型的数据
  20. {
  21. html: /html/
  22. json: /json/
  23. script: /(?:java|ecma)script/
  24. xml: /xml/
  25. }
  26. */
  27. if ( contents[ type ] && contents[ type ].test( ct ) ) {
  28. dataTypes.unshift( type );
  29. /*
  30. 这里我们显然是匹配到了json这一项,所以dataTypes中加上一项[‘json‘]
  31. */
  32. break;
  33. }
  34. }
  35. }
  36. // Check to see if we have a response for the expected dataType
  37. if ( dataTypes[ 0 ] in responses ) {
  38. finalDataType = dataTypes[ 0 ];
  39. //如果这个类型的数据在responses中正好有,那么就直接将最终类型定义为dataType中的这一项,本例中,dataTypes[0]为‘json‘,但实际返回的响应是text。responses就是根据相应内容生成的响应对象,这里是"{text:"{"username":"ruby","age":"18"}"}".
  40. } else {
  41. // Try convertible dataTypes
  42. for ( type in responses ) {
  43. if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
  44. //检测responses中的各个类型的值是否可以转换为我们想得到的类型, 本例中这里的type为‘text‘,s.converters定义的是各种转换用到的函数,比如s.converters[‘text json‘]=JSON.parse。本例中这里是可以转换的。
  45. /*
  46. 还是列出来吧:
  47. s.converters:{
  48. "text script": function( text ) {
  49. jQuery.globalEval( text );
  50. return text;
  51. },
  52. // Convert anything to text
  53. "* text": String,
  54. // Text to html (true = no transformation)
  55. "text html": true,
  56. // Evaluate text as a json expression
  57. "text json": jQuery.parseJSON,
  58. // Parse text as xml
  59. "text xml": jQuery.parseXML
  60. }
  61. */
  62. finalDataType = type;
  63. break;
  64. }
  65. if ( !firstDataType ) {
  66. firstDataType = type;
  67. }
  68. }
  69. // Or just use first one
  70. finalDataType = finalDataType || firstDataType;
  71. }
  72. // If we found a dataType
  73. // We add the dataType to the list if needed
  74. // and return the corresponding response
  75. if ( finalDataType ) {
  76. if ( finalDataType !== dataTypes[ 0 ] ) {
  77. dataTypes.unshift( finalDataType );
  78. //完善s.dataTypes中的值,即完善响应数据的类型,此时为[‘text‘,‘json‘]
  79. }
  80. return responses[ finalDataType ];
  81. //最终返回responses[‘text‘]
  82. }
  83. }

再来看ajaxConvert方法:

  1. /* Chain conversions given the request and the original response
  2. * Also sets the responseXXX fields on the jqXHR instance
  3. */
  4. function ajaxConvert( s, response, jqXHR, isSuccess ) {
  5. var conv2, current, conv, tmp, prev,
  6. converters = {},
  7. // Work with a copy of dataTypes in case we need to modify it for conversion
  8. dataTypes = s.dataTypes.slice();
  9. //数组copy这么写?不知道为啥~你知道的话还望不吝赐教~
  10. // Create converters map with lowercased keys
  11. if ( dataTypes[ 1 ] ) {
  12. for ( conv in s.converters ) {
  13. converters[ conv.toLowerCase() ] = s.converters[ conv ];
  14. //构造一个转换对象,内容是s.converters中的那些转换函数.
  15. }
  16. }
  17. current = dataTypes.shift();
  18. // Convert to each sequential dataType
  19. while ( current ) {
  20. if ( s.responseFields[ current ] ) {
  21. jqXHR[ s.responseFields[ current ] ] = response;
  22. //这里给jqXHR即jquery构造出来的XMLHttpRequest对象赋值,在本例中,它在此添加了两个属性,一个是responseText,一个是responseJson
  23. }
  24. // Apply the dataFilter if provided
  25. if ( !prev && isSuccess && s.dataFilter ) {
  26. response = s.dataFilter( response, s.dataType );
  27. }
  28. prev = current;
  29. current = dataTypes.shift();
  30. //记住第一个类型,再获取第二个类型,这里的prev为‘text’, current为‘json‘。
  31. if ( current ) {
  32. // There‘s only work to do if current dataType is non-auto
  33. if ( current === "*" ) {
  34. current = prev;
  35. // Convert response if prev dataType is non-auto and differs from current
  36. } else if ( prev !== "*" && prev !== current ) {
  37. // Seek a direct converter
  38. conv = converters[ prev + " " + current ] || converters[ "* " + current ];
  39. //看看是否有prev类转current类的转换方法
  40. // If none found, seek a pair
  41. if ( !conv ) {
  42. for ( conv2 in converters ) {
  43. // If conv2 outputs current
  44. tmp = conv2.split( " " );
  45. if ( tmp[ 1 ] === current ) {
  46. // If prev can be converted to accepted input
  47. conv = converters[ prev + " " + tmp[ 0 ] ] ||
  48. converters[ "* " + tmp[ 0 ] ];
  49. if ( conv ) {
  50. // Condense equivalence converters
  51. if ( conv === true ) {
  52. conv = converters[ conv2 ];
  53. // Otherwise, insert the intermediate dataType
  54. } else if ( converters[ conv2 ] !== true ) {
  55. current = tmp[ 0 ];
  56. dataTypes.unshift( tmp[ 1 ] );
  57. }
  58. break;
  59. }
  60. }
  61. }
  62. }
  63. // Apply converter (if not an equivalence)
  64. if ( conv !== true ) {
  65. // Unless errors are allowed to bubble, catch and return them
  66. if ( conv && s[ "throws" ] ) {
  67. response = conv( response );
  68. } else {
  69. try {
  70. response = conv( response );
  71. //转换为我们想要的数据类型,截至此我们已经得到想要的json数据啦
  72. } catch ( e ) {
  73. return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
  74. }
  75. }
  76. }
  77. }
  78. }
  79. }
  80. return { state: "success", data: response };
  81. }

上面基本根据当前案例进行代码解析,很多情况没有一一列出,感兴趣的童鞋可以通过打断点调试的方式来解析代码。

来自为知笔记(Wiz)

时间: 2024-10-12 23:08:43

jquery的http请求对响应内容的处理的相关文章

Fiddler修改请求或响应内容

1.修改请求内容 方法一:设置请求前断点,修改请求后发送 1)设置断点 2)选中请求,在inspectors下修改请求内容 3)修改请求后,点击Break on Response按钮,进行请求的发送 4)点击Run to Completion,将响应结果返回 说明,只修改请求内容可跳过第3步,直接进行第4步操作 方法二:重发请求时修改请求参数,修改后发送请求 2.修改响应结果 方法一:修改请求参数后修改响应结果 修改请求参数-->点击Break on Response-->修改响应结果--&g

发送请求获取响应内容

C#请求url,获取响应的脚本 public string ResultOfApi(string url) { //发送请求 HttpWebRequest request = null; HttpWebResponse response = null; request = (HttpWebRequest)HttpWebRequest.Create(url); request.Method = "Get"; request.ContentType = "application

Java 纯HTTP Get请求获取响应内容,如果302,继而获取重定向后的响应内容。

public static void main(String[] args) {      try {        StringBuffer buffer = new StringBuffer();                  String url = "http://localhost:8080/istock/login?u=name&p=pass";               System.out.println("访问地址:" + url);

Fiddler插件 --- 解密Elong Mapi请求参数及响应内容

当前问题: 在我们日常的Web/App测试过程中, Fiddler是一大辅助利器:在我们团队,也经常使用Fiddler进行App抓包测试. 艺龙 App使用的REST(内部称为Mapi)接口,在使用过程中有如下特点: 1.接口请求入参:不论是GET还是POST接口:为保证隐私及数据安全,其入参均会经过一次AES加密:然后做一次Encode处理: 比如: 好吧,不经过解密,我也不知道req参数中又臭又长的到底是什么鬼: 2.接口响应,一般是经过Gzip或lzss压缩的: 这就导致在使用Fiddle

Web Service之Soap请求响应内容中文编码解密

java模拟Soap请求测试Web Service接口,发现Web Service响应内容中的中文竟然是编码格式.比如: 中文:退保成功 Soap中文编码:退保成功 我仔细分析后发现,退编码实际上就是Unicode编码的Soap版,正规的Unicode编码是\u9000,Soap改成自己的格式&#x[4位内容];格式. 还有其他的比如: 换行,Soap编码: 单引号,Soap为转换为html编码:' 与号,Soap为转换为html编码:& 小于号,Soap为转换为html

Django请求生命周期之响应内容

Django请求生命周期: 1.发送http请求2.服务器接受,根据请求头中的url在路由关系表中进行匹配(从上到下)3.匹配成功后,执行指定的views函数 URL -> 函数 ==>FBV URL -> 类 ==>CBV4.业务处理 - 根据个人需求自定 - 操作数据库 - 原生SQL - Django ORM ==> 返回给用户的结果 <== - 响应内容 - 响应头 - 响应体 原文地址:https://www.cnblogs.com/ray-h/p/10241

PHP服务器文件管理器开发小结(三):使用jQuery提交AJAX请求

本节将讨论使用jQuery提交AJAX请求的基本方法,并完成显示首文件夹的基本方法. 同时,本节也将讨论使用图片链接提交请求的基本方法. jQuery是一套强大的JS库,将复杂的JS操作封装成简洁的语句,并提供对AJAX的支持.通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本.HTML.XML 或 JSON - 同时您能够把这些外部数据直接载入网页的被选元素中.编写常规的 AJAX 代码并不容易,因为不同的浏览器对 AJAX 的实现

js&amp;jquery跨域详解jsonp,jquery并发大量请求丢失回调bug

URL 说明 是否允许通信 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不

使用 jQuery Deferred 和 Promise 创建响应式应用程序

这篇文章,我们一起探索一下 JavaScript 中的 Deferred 和 Promise 的概念,它们是 JavaScript 工具包(如Dojo和MochiKit)中非常重要的一个功能,最近也首次亮相于 流行的 JavaScript 库 jQuery(已经是1.5版本的事情了). Deferred 提供了一个抽象的非阻塞的解决方案(如 Ajax 请求的响应),它创建一个 “promise” 对象,其目的是在未来某个时间点返回一个响应.如果您之前没有接触过 “promise”,我们将会在下面