AJAX

前奏

混编模式历史

php脚本 网页开发

AJAX - Asynchronous JavaScript and XML

异步的JavaScript和XML

历史

AJAX历史:

  • 1999 IE5.0 允许JS脚本向服务器单独发起HTTP请求的新功能
  • 2004 GMAIL 推出异步邮件更新服务
  • 2005 Google Map 异步更新地图服务
  • 2005 AJAX被大厂公认命名
  • 2006 W3C发布AJAX国际标准

所以说,AJAX是JavaScript脚本发起HTTP通信

应用

AJAX初始应用场景:

JavaScript异步通信,请求服务器返回XML文档,并从XML文档提取数据,再不刷新整个网页的基础上,渲染到网页响应的位置。

创建

创建XMLHttpRequest对象

XMLHttpRequest & ActiveX对象

作用:JS脚本发起HTTP请求时必须通过XMLHttpRequest对象,也是通过AJAX进行浏览器与服务器通信的接口,不局限于XML,可以发送仍和格式的数据

实例化对象

  1. var xhr = new XMLHttpRequest();

兼容IE5/IE6使用Active对象

  1. var xhr = new ActiveXObject('Microsoft.XMLHTTP');

发送HTTP请求

  1. xhr.open(method, url, async);

参数:

  • method:请求方式
  • url:请求发送地址
  • async:是否同步,默认为异步false
  1. xhr.send();

参数:

  • POST需要请求体

状态码

发送请求时的响应任务

onreadystatechange事件:挂载到XMLHttpRequest对象上的事件

  • readyState状态:通过XMLHttpRequest对象发送HTTP请求的各阶段状态码(0-4)

    • 0:请求未初始化
    • 1:服务器连接已建立
    • 2:请求已接受
    • 3:请求处理中
    • 4:请求已完成,且响应已就绪
  • status状态:服务器响应的状态码(200, 404…)
  • statusText:状态提示

    • 200, OK, 访问正常
    • 301,Move Permanently,永久移动
    • 302,Not Modified,暂时移动
    • 304,Not Modified,未修改
    • 307,Temporary Redirect,暂时重定向
    • 401,Unauthorized,未授权
    • 403,Forbidden,禁止访问
    • 404,Not Found,未发现指定网址
    • 500,Internet Server Error,服务器发生错误

注:readyState仅仅是针对请求与响应的状态码,获取资源是否成功取决于status状态

服务器响应

  • responseText:获取字符串数据
  • responseXML:获取XML数据

原生HTTP请求写法:

注:POST请求写法,必须带请求头xhr.setRequestHeader()

  1. var xhr;
  2. if (window.XMLHttpRequest) {
  3. xhr = new XMLHttpRequest();
  4. } else {
  5. xhr = new ActiveXObject('Microsoft.XMLHTTP');
  6. }
  7. console.log(xhr.readyState); //0 请求未初始化
  8. xhr.open('GET', 'http://localhost', true);
  9. // POST请求写法,必须带请求头
  10. xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  11. xhr.send('status=1&flag=1');
  12. console.log(xhr.readyState); //1 服务器连接已建立
  13. xhr.onreadystatechange = function () {
  14. console.log(xhr.readyState);
  15. //2 请求已接受
  16. //3 请求处理中
  17. //4 请求已完成,且响应已就绪
  18. if (xhr.readyState === 4 && xhr.status === 200) {
  19. console.log(JSON.parse(xhr.responseText));
  20. }
  21. }

版本

XMLHttpRequest版本

标准:

  • Level 1 缺点:

    • 无法发送跨域请求
    • 不能非纯文本的数据
    • 无法获取传输速度
  • Level 2 改进:

    • 可以发送跨域请求
    • 支持获取二进制数据(非纯文本数据)
    • 支持上传文件
    • formData对象
    • 可以获取传输进度
    • 可以设置超时时间

兼容性

  • IE8/9/Opera Mini不支持xhr对象
  • IE10/11不支持响应类型为JSON
  • 部分浏览器不支持超时设置
  • 部分浏览器不支持blob(文件对象的二进制数据)

五个事件

  • xhr.onloadstart:绑定HTTP请求发出的监听函数
  • xhr.onerror:绑定请求失败的监听函数(修改封装的AJAX)
  • xhr.onload:绑定请求成功完成的监听函数
  • xhr.onabort:绑定请求终止(调用abort()方法)的监听函数
  • xhr.onloadend:绑定请求完成(不管成功与失败)的监听函数

触发顺序:

  1. loadstart
  2. readyState === 4
  3. load/error/abort
  4. loadend

异步

异步与同步

  • async = true(默认):Ajax异步发送请求时,不影响页码加载,用户操作以及Ajax程序后的执行
  • async = false:Ajax同步发送请求时,浏览器必须等到请求完成并响应成功后,Ajax程序后续的程序才会执行

响应数据

dataType返回的数据类型

  • JSON

  • TEXT

  • XML

  • responseText:获取字符串数据

  • responseXML:获取XML数据

封装

封装AJAX

  1. /**
  2. * AJAX封装
  3. *
  4. * 调用写法一:
  5. * $.ajax({
  6. * url: 'xxx',
  7. * type: 'POST',
  8. * dataType: 'JSON',
  9. * data: {
  10. * status: 1
  11. * },
  12. * success: function (data) {
  13. * console.log(data);
  14. * }
  15. * })
  16. *
  17. * 调用写法二:
  18. * $.post('http://localhost/xxx', { status: 1 }, function (data) { console.log(data); });
  19. *
  20. * 调用写法三:
  21. * $.get('http://localhost/xxx?status=1', function (data) { console.log(data); });
  22. *
  23. *
  24. */
  25. //老写法:
  26. // var $ = {
  27. // ajax: function (opt) {
  28. // var url = opt.url;
  29. // console.log(url);
  30. // },
  31. // post: function () {
  32. // console.log('post');
  33. // },
  34. // get: function () {
  35. // console.log('get');
  36. // }
  37. // }
  38. // 模块化写法
  39. var $ = (function () {
  40. //利用_doAjax函数传参拿到局部作用域ajax函数里的形参
  41. function _doAjax(opt) {
  42. //兼容IE5,IE6
  43. var o = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  44. //IE4及以下
  45. if (!o) {
  46. throw new Error('您的浏览器不支持异步发起HTTP请求');
  47. }
  48. //初始化传入的配置
  49. var opt = opt || {},
  50. // console.log(opt); //{type: "POST"}
  51. //初始化请求类型为GET
  52. type = (opt.type || 'GET').toUpperCase(),
  53. // console.log(type); //POST
  54. // 同步/异步 false/true
  55. async = '' + opt.async === 'false' ? false : true,
  56. url = opt.url,
  57. //如果GET请求就为null
  58. data = opt.data || null,
  59. //响应数据
  60. dataType = opt.dataType || 'JSON',
  61. timeout = opt.timeout || 30000,
  62. error = opt.error || function () {},
  63. success = opt.success || function () {},
  64. //不管成功或失败都执行complete函数
  65. complete = opt.complete || function () {},
  66. // 初始化定时器
  67. t = null;
  68. if (!url) {
  69. throw new Error('您没有填写url');
  70. }
  71. /**发送HTTP请求
  72. * @type 请求类型
  73. * @url 请求地址
  74. * @async 异步/同步
  75. */
  76. o.open(type, url, async);
  77. //超时设置 写法一: 设置超时时间 30s
  78. //兼容性不太好
  79. // o.ontimeout = 30000;
  80. //设置POST请求头
  81. //如果为真走后面
  82. type === 'POST' && o.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  83. //如果是GET请求,不用传参数
  84. o.send(type === 'GET' ? null : formatDatas(data));
  85. //监听响应事件
  86. o.onreadystatechange = function () {
  87. if (o.readyState === 4) {
  88. //请求已完成,且响应已就绪
  89. if (o.status >= 200 && o.status < 300 && o.status === 304) {
  90. switch (dataType.toUpperCase()) {
  91. case 'JSON':
  92. // 成功时响应服务器JSON数据
  93. success(JSON.parse(o.responseText));
  94. break;
  95. case 'TEXT':
  96. // 成功时响应服务器文本数据
  97. success(o.responseText);
  98. break;
  99. case 'XML':
  100. // 成功时响应服务器XML数据
  101. success(o.responseXML);
  102. break;
  103. default:
  104. // 默认响应服务器JSON数据
  105. success(JSON.parse(o.responseText));
  106. }
  107. } else {
  108. error();
  109. }
  110. // 无论成功与否都要执行complete函数
  111. complete();
  112. clearTimeout(t);
  113. t = null;
  114. o = null;
  115. }
  116. }
  117. // 超时设置 写法一:
  118. //只要超时就会执行的函数
  119. //兼容性不太好
  120. // o.ontimeout = function () {
  121. // //o对象的所有程序都会中止
  122. // o.abort();
  123. // //并销毁对象
  124. // o = null;
  125. // }
  126. // 超时设置 写法二:
  127. t = setTimeout(function () {
  128. //o对象的所有程序都会中止
  129. o.abort();
  130. clearTimeout(t);
  131. t = null;
  132. o = null;
  133. //抛出错误
  134. throw new Error('This request has been timeout for' + url);
  135. }, timeout);
  136. }
  137. //希望将{status:1,flag:2}转为'status=1&flag=2'
  138. //格式化传入的data数据
  139. function formatDatas(obj) {
  140. var str = '';
  141. for (var key in obj) {
  142. str += key + '=' + obj[key] + '&';
  143. }
  144. //去掉最后一项的 &
  145. //正则规则:以&结尾 替换为空字符
  146. return str.replace(/&$/, '');
  147. }
  148. return {
  149. ajax: function (opt) {
  150. _doAjax(opt);
  151. },
  152. get: function (url, dataType, successCB, errorCB, completeCB) {
  153. _doAjax({
  154. type: 'GET',
  155. url: url,
  156. dataType: dataType,
  157. success: successCB,
  158. error: errorCB,
  159. complete: completeCB
  160. });
  161. },
  162. post: function (url, data, dataType, successCB, errorCB, completeCB) {
  163. _doAjax({
  164. type: 'POST',
  165. url: url,
  166. data: data,
  167. dataType: dataType,
  168. success: successCB,
  169. error: errorCB,
  170. complete: completeCB
  171. });
  172. }
  173. }
  174. })();