image.png

一、Ajax是什么

Ajax是一种异步请求数据的web开发技术,在不需要重新整体刷新(局部刷新)页面的情况下, 通过异步请求加载后台数据,并在网页上呈现出来。常见运用场景

  • 表单验证是否登入成功
  • 百度搜索下拉框提示
  • 快递单号查询

由于AJAX请求获取的是数据而不是HTML文档,可以减少网络数据的传输量,提高用户体验。

二、Ajax原理

Ajax请求数据依赖浏览器提供的XMLHttpRequest对象,可以使浏览器可以发出HTTP请求与接收HTTP响应,而浏览器接着做其他事情,等收到XHR返回来的数据再渲染页面。
image.png

三、Ajax基础

XMLHttpRequest有两种执行模式:同步(synchronous)异步(asynchronous)
要发送请求,需要 3 个步骤:

1. 创建 XMLHttpRequest

  1. let xhr = new XMLHttpRequest();
  2. // 兼容性处理
  3. if(window.XMLHttpRequest){
  4. xhr = new XMLHttpRequest();
  5. }else{
  6. xhr = new ActiveXObject('IE.XMLHttp')
  7. }

2. 初始化配置请求

xhr.open(method, URL, [async, user, password])
主要参数:

  • method —— HTTP 方法。通常是 "GET""POST"
  • URL —— 要请求的 URL,通常是一个字符串,也可以是 URL 对象。
  • async —— 如果显式地设置为 false,那么请求将会以同步的方式处理,我们稍后会讲到它。
  • userpassword —— HTTP 基本身份验证(如果需要的话)的登录名和密码。

    open 调用与其名称相反,不会建立连接。它仅配置请求,而网络活动仅以 send 调用开启

3. 发送请求

xhr.send([body])
这个方法会建立连接,并将请求发送到服务器。可选参数 body 包含了 request body。

  • GET 没有 request body。
  • POST 使用 body 将数据发送到服务器。


4. 监听xhr事件以获取响应。

这三个事件是最常用的:

  • load —— 当请求完成(即使 HTTP 状态为 400 或 500 等),并且响应已完全下载。
  • error —— 当无法发出请求,例如网络中断或者无效的 URL。
  • progress —— 在下载响应期间定期触发,报告已经下载了多少。


erroraborttimeoutload 事件是互斥的。其中只有一种可能发生。

旧版

  1. const xhr = new XMLHttpRequest()
  2. xhr.onreadystatechange = () => {
  3. if (xhr.readystate == 4) {
  4. if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
  5. alert(xhr.responseText)
  6. } else {
  7. alert("Request was unsuccessful: " + xhr.status)
  8. }
  9. }
  10. }
  11. xhr.open("get", "example.php", true)
  12. xhr.send(null)

新版:
load事件帮助我们节省了readstatechange事件,不必在XHR对象实例上监听readyState属性的变化

  1. // 1. 创建一个 new XMLHttpRequest 对象
  2. let xhr = new XMLHttpRequest();
  3. // 2. 配置它:从 URL /article/.../load GET-request
  4. xhr.open('GET', '/article/xmlhttprequest/example/load');
  5. // 3. 通过网络发送请求
  6. xhr.send();
  7. // 4. 当接收到响应后,将调用此函数
  8. xhr.onload = function() {
  9. if (xhr.status != 200) { // 分析响应的 HTTP 状态
  10. alert(`Error ${xhr.status}: ${xhr.statusText}`); // 例如 404: Not Found
  11. } else { // 显示结果
  12. alert(`Done, got ${xhr.response.length} bytes`); // response 是服务器响应
  13. }
  14. };
  15. xhr.onprogress = function(event) {
  16. if (event.lengthComputable) {
  17. alert(`Received ${event.loaded} of ${event.total} bytes`);
  18. } else {
  19. alert(`Received ${event.loaded} bytes`); // 没有 Content-Length
  20. }
  21. };
  22. xhr.onerror = function() {
  23. alert("Request failed");
  24. };

四、XMLHttpRequest对象

方法

  • open():准备启动一个AJAX请求;
  • setRequestHeader():设置请求头部信息;
  • send():发送AJAX请求;
  • getResponseHeader(): 获得响应头部信息;
  • getAllResponseHeader():获得一个包含所有头部信息的长字符串;
  • abort():取消异步请求;
  • onreadystatechange:当XML实例的readyState属性变化时,就会触发该事件的发生;

属性

  • readyState:表示“请求”/“响应”过程的当前活动阶段
  • status:响应的HTTP状态;
  • statusText:HTTP状态的说明;
  • responseText/response:包含响应主体返回文本;
  • responseType:设置响应格式
  • withCredentials : 是否将 cookie 和 HTTP 授权发送到其他域,默认false


响应类型

使用 xhr.responseType 属性来设置响应格式:

  • ""默认)—— 响应格式为字符串,
  • "text" —— 响应格式为字符串,
  • "arraybuffer" —— 响应格式为 ArrayBuffer
  • "blob" —— 响应格式为 Blob
  • "document" —— 响应格式为 XML document(可以使用 XPath 和其他 XML 方法),
  • "json" —— 响应格式为 JSON(自动解析)。

readyState

XMLHttpRequest 的状态(state)会随着它的处理进度变化而变化。可以通过 xhr.readyState 来了解当前状态。

  1. UNSENT = 0; // 初始状态
  2. OPENED = 1; // open 被调用
  3. HEADERS_RECEIVED = 2; // 接收到 response header
  4. LOADING = 3; // 响应正在被加载(接收到一个数据包)
  5. DONE = 4; // 请求完成

XMLHttpRequest 对象以 0123 → … → 34 的顺序在它们之间转变。
每当通过网络接收到一个数据包,就会重复一次状态 3
可以使用 readystatechange 事件来跟踪它们

  1. xhr.onreadystatechange = function() {
  2. if (xhr.readyState == 3) {
  3. // 加载中
  4. }
  5. if (xhr.readyState == 4) {
  6. // 请求完成
  7. }
  8. };

在非常老的代码中找到 readystatechange 这样的事件监听器。如今,它已被 load/error/progress 事件处理程序所替代。

GET请求和POST请求

GET请求

  • GET请求用于获取数据,将查询参数追加到URL的末尾,令服务器解析。
  • 查询字符串中每个参数的名和值都必须使用encodeURIComponent()进行编码(这是因为URL中有些字符会引起歧义,例如“&”)。

    POST请求

    POST请求用于向服务器发送应该被保存的数据,包括表单数据或JSON字符串,使用send(data)。那么这些数据应该放在何处呢?毕竟,我们的 ```javascript // 表单FormData let formData = new FormData([form]); // 创建一个对象,可以选择从
    中获取数据 formData.append(name, value); // 附加一个字段 let xhr = new XMLHttpRequest(); xhr.open(“POST”, “/article/xmlhttprequest/post/user”); xhr.send(formData);

// JSON字符串 let xhr = new XMLHttpRequest(); let json = JSON.stringify({ name: “John”, surname: “Smith” });

xhr.open(“POST”, ‘/submit’) // 有了它,很多服务端框架都能自动解码 JSON xhr.setRequestHeader(‘Content-type’, ‘application/json; charset=utf-8’); xhr.send(json);

  1. 注意以下两点:
  2. 1. `.send()`方法的参数是**不可为空**的,**GET请求**,也需要使用`send(null)`方法;
  3. 1. 两种向服务器发送数据的方式:**表单提交**以及**发送POST请求**;
  4. <a name="019eff4f"></a>
  5. ## HTTP-header
  6. `XMLHttpRequest` 允许发送自定义 header,并且可以从响应中读取 header。<br />HTTP-header 有三种方法:
  7. <a name="0AsYJ"></a>
  8. ### `setRequestHeader(name, value)`
  9. ```javascript
  10. xhr.setRequestHeader('Content-Type', 'application/json');

Header 的限制

  • 一些 header 是由浏览器专门管理的,为了用户安全和请求的正确性,XMLHttpRequest 不允许更改它们例如Referer****Host
  • 不能移除 header
    • XMLHttpRequest 的另一个特点是不能撤销 setRequestHeader。一旦设置了 header,就无法撤销了。其他调用会向 header 中添加信息,但不会覆盖它。
  1. xhr.setRequestHeader('X-Auth', '123');
  2. xhr.setRequestHeader('X-Auth', '456');
  3. // header 将是:
  4. // X-Auth: 123, 456

getResponseHeader(name)

获取具有给定 name 的 header(Set-CookieSet-Cookie2 除外)。

getAllResponseHeaders()

返回除 Set-CookieSet-Cookie2 外的所有 response header

取消异步请求

可以随时终止请求。调用 xhr.abort() 即可:

  1. xhr.abort(); // 终止请求

它会触发 abort 事件,且 xhr.status 变为 0

进度事件

progress 事件:加载进度条效果

仅在下载阶段触发

onprogress事件处理程序会接收到一个event对象,其有3个属性

  • lengthComputable:表示进度信息是否可用的布尔值;
  • position:表示目前接收的字节数;
  • totalSize:表示根据Content-Length响应头部确定的预期字节数;
    1. const xhr = new XMLHttpRequest()
    2. xhr.onload = () => {
    3. if ((xhr.status >= 200 && xhr.status <300) || xhr.status == 304) {
    4. alert(xhr.responseText)
    5. } else {
    6. alert("Something wrong!")
    7. }
    8. }
    9. // 加载进度条
    10. xhr.onprogress = function(event) {
    11. const divStatus = document.getElementById("status")
    12. if (event.lengthComputable) {
    13. divStatus.innerHTML = `Received ${event.postion} of ${event.totalSize} bytes`
    14. }
    15. }
    16. xhr.open("get", "example.php", true)
    17. xhr.send(null)
    注意需要在.open()方法前调用onprogress事件处理程序。
    **

    upload事件:用于跟踪上传事件

    类似于xhr**对象,**它会生成事件

xhr.upload 仅在上传时触发它们:

  • loadstart —— 上传开始。
  • progress —— 上传期间定期触发。
  • abort —— 上传中止。
  • error —— 非 HTTP 错误。
  • load —— 上传成功完成。
  • timeout —— 上传超时(如果设置了 timeout 属性)。
  • loadend —— 上传完成,无论成功还是 error。 ``javascript xhr.upload.onprogress = function(event) { alert(Uploaded ${event.loaded} of ${event.total} bytes`); };

xhr.upload.onload = function() { alert(Upload finished successfully.); };

xhr.upload.onerror = function() { alert(Error during the upload: ${xhr.status}); }; ```