紫影基地

 找回密码
 立即注册
查看: 115|回复: 0

ajax httprequest 详解

[复制链接]
阅读字号:

2002

主题

2117

帖子

21万

积分

超级版主

Rank: 8Rank: 8

积分
210303
发表于 2024-4-21 17:12:35 | 显示全部楼层 |阅读模式


  1. js
  2. 同时被 2 个专栏收录
  3. 20 篇文章0 订阅
  4. 订阅专栏

  5. ajax
  6. 4 篇文章0 订阅
  7. 订阅专栏
  8. 概述
  9. AJAX是“Asynchronous Javascript And XML”的缩写,中文译作“异步JavaScript和XML”。使用AJAX可以通过HTTP协议与服务器交互数据,可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
  10. 传统的网页如果需要更新内容,必须重新加载整个网页页面。此外,它也是实现前端与后端解耦的重要技术手段。

  11. 为了实现AJAX技术,早期微软的IE5、IE6浏览器内嵌了XMLHTTP组件,其它浏览器比如Opera、Mozila的早期版本则内嵌了XMLHttpRequest组件。XMLHTTP与XMLHttpRequest有很多相同的属性和方法,因此XMLHTTP也被一起叫做XMLHttpRequest,简称XHR。后来XHR被W3C组织标准化。各浏览器也逐渐按照W3C制定的标准来实现XHR,到目前为止,仍然有部分的属性和方法不被部分浏览器支持。下面的图片截取于 Can I Use网站,它描述了目前各浏览器对XHR的兼容情况。因此,在使用XHR开发时需要注意兼容性,不过笔者认为,老版本浏览器的占有量会越来越少,新版本的浏览器可能会更加严格的按照W3C制定的标准来实现XHR,兼容性问题就会被慢慢淡化,Jquery框架在2.2的版本在实例化XHR时就不考虑IE5、IE6的兼容性问题了。

  12. 各浏览器对XMLHttpRequest的兼容情况

  13. XHR实例的创建
  14. 为了实现兼容IE5、IE6浏览器版本,所以可以用下面的代码创建XHR实例。

  15. var xhr;
  16. if (window.XMLHttpRequest)
  17. {
  18.     //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
  19.     xhr=new XMLHttpRequest();
  20. }
  21. else
  22. {
  23.     // IE6, IE5 浏览器执行代码
  24.     xhr=new ActiveXObject("Microsoft.XMLHTTP");
  25. }
  26. 1
  27. 2
  28. 3
  29. 4
  30. 5
  31. 6
  32. 7
  33. 8
  34. 9
  35. 10
  36. 11
  37. XHR请求
  38. XHR可以通过HTTP协议与服务器交换数据,要发送HTTP请求要使用到下面这些方法和属性:

  39. open方法
  40. open方法用于创建HTTP请求,但是请求并未发送,其定义如下:

  41. open(method, url [, async = true [, username = null [, password = null]]])
  42. 1
  43. 参数method定义请求的类型,如GET、POST方法等等,大小写不敏感
  44. 参数url定义请求的URL地址
  45. 参数async定义是否异步处理请求,true(异步)或者false(同步),默认为true
  46. 参数username定义用户名,不常用,默认为null
  47. 参数password定义密码,不常用,默认为null
  48. setRequestHeader方法
  49. setRequestHeader方法用于向请求添加HTTP头,其定义如下:

  50. setRequestHeader(name, value)
  51. 1
  52. 参数name定义HTTP请求头部的名称
  53. 参数value定义HTTP请求头部的值
  54. 注意:
  55. 1. setRequestHeader方法必须在open方法调用之后、send方法之前调用,否则会出现异常
  56. 2. setRequestHeader方法可以连续调用多次,如果已经存在同名的HTTP头时,最终结果是追加而不是覆盖

  57. //例子1
  58. client.setRequestHeader('X-Test', 'one');
  59. client.setRequestHeader('X-Test', 'two');
  60. //最后的结果为X-Test: one, two

  61. //例子2
  62. client.setRequestHeader('X-Test', 'one');
  63. client.setRequestHeader('X-Test', 'one');
  64. //最后的结果为X-Test: one, one
  65. 1
  66. 2
  67. 3
  68. 4
  69. 5
  70. 6
  71. 7
  72. 8
  73. 9
  74. timeout属性
  75. timeout属性用于设置HTTP请求的超时时间,单位毫秒。当发生超时时,会触发ontimeout事件。在IE中,超时属性只能在调用 open() 方法之后且在调用 send() 方法之前设置。

  76. upload属性
  77. upload用于在数据传输到服务器时收集一些传输信息,比如上传了多少字节,总共多少字节等,其里面还包含了一些事件回调。

  78. send方法
  79. send方法用于发送open方法创建的HTTP请求,其定义如下:

  80. send([body = null])
  81. 1
  82. 参数body定义HTTP请求的数据,当HTTP请求的方法为GET、HEAD时,该参数被忽略。body的类型可以为ArrayBuffer(二进制缓冲数组)、Blob(二进制大对象)、Document(类似XML格式的数据)、DOMString(字符串)、FormData(表单)。
  83. 上面几种数据类型的介绍可参考:

  84. ArrayBuffer、Blob、Document、DOMString、FormData类型的数据介绍

  85. abort方法
  86. 当请求发送后如果想终止这个请求,则可以调用abort方法,其定义如下:

  87. abort()
  88. 1
  89. XHR事件回调
  90. 当XHR发送异步请求后,我们无法知道请求是否发生了异常、请求何时到达服务器、服务器何时返回响应数据。XHR为我们提供了很多的事件回调,用来通知我们请求及响应状态的改变。下面的接口定义语言描述了跟XHR相关的事件接口定义。

  91. interface XMLHttpRequestEventTarget : EventTarget {
  92.   // event handlers
  93.   attribute EventHandler onloadstart;
  94.   attribute EventHandler onprogress;
  95.   attribute EventHandler onabort;
  96.   attribute EventHandler onerror;
  97.   attribute EventHandler onload;
  98.   attribute EventHandler ontimeout;
  99.   attribute EventHandler onloadend;
  100. };

  101. interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
  102. };

  103. interface XMLHttpRequest : XMLHttpRequestEventTarget {
  104.   // event handler
  105.   attribute EventHandler onreadystatechange;
  106.   // states
  107.   //XHR的状态定义
  108.   const unsigned short UNSENT = 0;
  109.   const unsigned short OPENED = 1;
  110.   const unsigned short HEADERS_RECEIVED = 2;
  111.   const unsigned short LOADING = 3;
  112.   const unsigned short DONE = 4;
  113.   //用于描述XHR的状态
  114.   readonly attribute unsigned short readyState;
  115.   // request
  116.   [SameObject] readonly attribute XMLHttpRequestUpload upload;
  117. };
  118. 1
  119. 2
  120. 3
  121. 4
  122. 5
  123. 6
  124. 7
  125. 8
  126. 9
  127. 10
  128. 11
  129. 12
  130. 13
  131. 14
  132. 15
  133. 16
  134. 17
  135. 18
  136. 19
  137. 20
  138. 21
  139. 22
  140. 23
  141. 24
  142. 25
  143. 26
  144. 27
  145. 28
  146. 29
  147. readyState属性用于描述XHR的状态,它有下面五种状态:
  148. 值        状态        描述
  149. 0        UNSENT        最初始状态,还未调用open方法
  150. 1        OPENED        已经调用了open方法
  151. 2        HEADERS_RECEIVED        已经调用了send方法,响应的HTTP头部和状态可以获取
  152. 3        LOADING        正在下载数据,下载的数据还不完整
  153. 4        DONE        数据下载完成
  154. - onreadystatechange属性可以指定一个回调函数,当XHR的状态(即readyState)发生改变时就会调用该函数,可以在这个回调函数中判断请求是否成功。

  155.    xhr.onreadystatechange = function() {
  156.         if (xhr.readyState == 4) {
  157.             //当XHR的状态为4时判断请求成功与否,然后处理响应的数据,虽然当XHR的状态为2或者3时可以获取到响应状态,但是此时的数据还未下载完全,不能处理响应数据
  158.             if (xhr.status == 200) {
  159.                 //请求成功,处理响应数据
  160.             } else {
  161.                 //请求失败
  162.             }
  163.         }
  164.     }
  165. 1
  166. 2
  167. 3
  168. 4
  169. 5
  170. 6
  171. 7
  172. 8
  173. 9
  174. 10
  175. upload属性代表上传数据的过程,它是XMLHttpRequestUpload的实例,XMLHttpRequestUpload继承XMLHttpRequestEventTarget接口,XMLHttpRequestEventTarget有7个回调方法,在数据上传的过程中会调用相应的方法。XHR也继承XMLHttpRequestEventTarget接口,因此它也拥有这些回调方法,但是它的回调方法大多都是从服务器下载响应数据的过程中触发的。
  176. 事件触发的时机
  177. upload的回调方法会在数据上传的过程中触发,XHR的回调方法大多在响应数据下载的过程中触发,具体的触发时机见下表:

  178. 事件        触发时机
  179. onreadystatechange        当readyState的值改变时触发,除了当它从非0变成0时
  180. onloadstart        当调用send方法时会触发xhr.onloadstart,然后会触发xhr.upload.onloadstart,代表开始上传数据
  181. onprogress        上传数据过程中会触发xhr.upload.onprogress,下载数据过程中会触发xhr.onprogress,onprogress每50ms会触发一次
  182. onabort        调用abort方法后会触发
  183. onerror        当发生网络异常的时候会触发,如果上传数据的过程还未结束,此时会先触发xhr.upload.onerror,然后再触发xhr.onerror;如果上传数据的过程已经结束,此时只会触发xhr.onerror
  184. onload        上传数据成功,会触发xhr.upload.onload;下载数据成功会触发xhr.onload
  185. ontimeout        当服务端响应的时间超过指定的timeout时间时,会触发此事件
  186. onloadend        上传数据完成(成功或者失败)时会触发xhr.upload.onloadend;下载数据完成(成功或失败)会触发xhr.onloadend
  187. 事件触发的顺序
  188. 通过下面的代码验证,可以得出事件触发的顺序。

  189. var xhr = new XMLHttpRequest();
  190.     xhr.timeout = 1;
  191.     //xhr events
  192.     xhr.onreadystatechange = function() {
  193.         console.log("onreadystatechange(),readyState=" + xhr.readyState);
  194.     }
  195.     xhr.onloadstart = function(event) {
  196.         console.log("onloadstart()");
  197.     }
  198.     xhr.onprogress = function(event) {
  199.         console.log("onprogress()");
  200.     }
  201.     xhr.onabort = function(event) {
  202.         console.log("onabort()");
  203.     }
  204.     xhr.onerror = function(event) {
  205.         console.log("onerror()");
  206.     }
  207.     xhr.onload = function(event) {
  208.         console.log("onload()");
  209.     }
  210.     xhr.ontimeout = function(event) {
  211.         console.log("ontimeout()");
  212.     }
  213.     xhr.onloadend = function(event) {
  214.             console.log("onloadend()");
  215.         }
  216.         //upload events
  217.     xhr.upload.onloadstart = function(event) {
  218.         console.log("upload.onloadstart()");
  219.     }
  220.     xhr.upload.onprogress = function(event) {
  221.         console.log("upload.onprogress()");
  222.     }
  223.     xhr.upload.onabort = function(event) {
  224.         console.log("upload.onabort()");
  225.     }
  226.     xhr.upload.onerror = function(event) {
  227.         console.log("upload.onerror()");
  228.     }
  229.     xhr.upload.onload = function(event) {
  230.         console.log("upload.onload()");
  231.     }
  232.     xhr.upload.ontimeout = function(event) {
  233.         console.log("upload.ontimeout()");
  234.     }
  235.     xhr.upload.onloadend = function(event) {
  236.         console.log("upload.onloadend()");
  237.     }
  238.     try {
  239.         xhr.open("POST", "http://localhost:8080/Server/test", true);
  240.         xhr.send("hello");
  241.     } catch (e) {
  242.         alert(e.toString());
  243.     }
  244. 1
  245. 2
  246. 3
  247. 4
  248. 5
  249. 6
  250. 7
  251. 8
  252. 9
  253. 10
  254. 11
  255. 12
  256. 13
  257. 14
  258. 15
  259. 16
  260. 17
  261. 18
  262. 19
  263. 20
  264. 21
  265. 22
  266. 23
  267. 24
  268. 25
  269. 26
  270. 27
  271. 28
  272. 29
  273. 30
  274. 31
  275. 32
  276. 33
  277. 34
  278. 35
  279. 36
  280. 37
  281. 38
  282. 39
  283. 40
  284. 41
  285. 42
  286. 43
  287. 44
  288. 45
  289. 46
  290. 47
  291. 48
  292. 49
  293. 50
  294. 51
  295. 52
  296. 53
  297. 54
  298. 55
  299. 打印的顺序如下:

  300. //调用了open方法
  301. onreadystatechange(),readyState=1
  302. //调用了send方法
  303. onloadstart()
  304. //上传数据过程中的事件回调
  305. upload.onloadstart()//开始上传请求数据
  306. upload.onprogress()//正在上传请求数据
  307. upload.onload()//成功上传请求数据
  308. upload.onloadend()//完成上传请求数据
  309. //下载响应数据过程中的事件回调
  310. onreadystatechange(),readyState=2//已经获取到响应头部和响应状态码
  311. onreadystatechange(),readyState=3//正在下载响应数据,改变状态
  312. onprogress()//正在下载响应数据
  313. onreadystatechange(),readyState=4//响应数据下载完成,改变状态
  314. onload()//成功下载响应数据
  315. onloadend()//完成下载响应数据
  316. 1
  317. 2
  318. 3
  319. 4
  320. 5
  321. 6
  322. 7
  323. 8
  324. 9
  325. 10
  326. 11
  327. 12
  328. 13
  329. 14
  330. 15
  331. 16
  332. 事件回调方法的参数
  333. XMLHttpRequestEventTarget里面的回调方法的参数类型为ProgressEvent,ProgressEvent的定义如下:

  334. interface ProgressEvent : Event {
  335.   readonly attribute boolean lengthComputable;//数据长度是否可计算的
  336.   readonly attribute unsigned long long loaded;//已经下载或者上传了多少字节
  337.   readonly attribute unsigned long long total;//需要下载或者上传的总字节数
  338. };
  339. 1
  340. 2
  341. 3
  342. 4
  343. 5
  344. 所以在onprogress方法回调中,可以通过loaded和total这两个属性来实现上传或者下载的进度条功能。

  345. 事件回调方法的添加方式
  346. 一种方式是直接为它指定函数的引用,如下方式:
  347.     xhr.onloadstart = function(event) {
  348.         console.log("onloadstart()");
  349.     }
  350. 1
  351. 2
  352. 3
  353. 从上面的定义中可以看出,事件接口都继承自EventTarget,EventTarget的定义如下,其中有addEventListener方法,第一个参数时事件名称,没有“on”前缀,第二个参数时回调方法,其它参数为可选。
  354. interface EventTarget {
  355.   void addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options);
  356.   void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options);
  357.   boolean dispatchEvent(Event event);
  358. };
  359. 1
  360. 2
  361. 3
  362. 4
  363. 5
  364. 因此下面的代码实现的效果与方式一相同

  365.     xhr.addEventListener("loadstart", function(event) {
  366.         console.log("loadstart()");
  367.     });
  368. 1
  369. 2
  370. 3
  371. XHR响应
  372. 了解了XHR的请求、XHR的事件回调之后,就剩下处理XHR响应的工作了,比如解析数据等等,要处理响应,需要了解下面的方法和属性。

  373. getResponseHeader方法
  374. getResponseHeader方法可以获取HTTP响应头指定键值的数据,其定义如下:

  375. getResponseHeader(ByteString name);
  376. 1
  377. 参数name为HTTP响应头部的键值
  378. getAllResponseHeaders方法
  379. getAllResponseHeaders方法可以获取所有的HTTP响应头的数据,其定义如下:

  380. getAllResponseHeaders()
  381. 1
  382. status和statusText属性
  383. status属性表示HTTP响应状态码,即200、404等;statusText属性表示HTTP响应状态的描述文本,即OK、Not Found等。

  384. responseType、response、responseText、responseXML属性
  385. 可以在发送请求之前设置responseType,用于指定返回的响应数据的类型,responseType的类型有以下几种:

  386. 类型        描述
  387. empty string        空字符串,这是默认值
  388. arraybuffer        二进制缓冲数组
  389. blob        二进制大对象
  390. document        文档类型
  391. json        JSON类型
  392. text        文本类型
  393. 处理响应数据时,需要根据responseType来判断返回的数据类型。当responseType为text或者empty string类型时可以使用responseText属性,为其它类型时调用responseText会发生异常;当responseType为document或者empty responseXML属性,为其它类型时调用responseXML会发生异常;当responseType不是empty string、text、document类型时,需要转换成具体的类型进行解析。

  394. 处理响应数据的时机
  395. 方式一:
  396.     xhr.onreadystatechange = function() {
  397.             if (xhr.readyState === 4) {
  398.                 if (xhr.status === 200) {
  399.                     //处理数据
  400.                 } else {
  401.                     //其它操作
  402.                 }
  403.             }
  404.         }
  405. 1
  406. 2
  407. 3
  408. 4
  409. 5
  410. 6
  411. 7
  412. 8
  413. 9
  414. 方式二:
  415.     xhr.onload = function(event) {
  416.         if (xhr.status === 200) {
  417.             //处理数据
  418.         } else {
  419.             //其它操作
  420.         }
  421.     }
  422. 1
  423. 2
  424. 3
  425. 4
  426. 5
  427. 6
  428. 7
  429. 通过XHR回调事件的触发时机我们可以知道,onreadystatechange回调会触发多次,因此方式二更优。
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|紫影基地

GMT+8, 2025-1-12 12:11 , Processed in 0.096796 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表