AJAX的入门与使用

319 阅读11分钟

Ajax

一、Ajax概念

什么是AJAX

AJAX 的英文全称为 Asynchronous JavaScript And XML,Asynchronous 是异步的意思。何为异步呢?在这里异步是指通过 AJAX 向服务器请求数据,在不刷新整个页面的情况下,更新页面上的部分内容

PixPin_2024-03-11_17-08-59.jpg

  1. 网页中发生一个事件(页面加载、按钮点击)0
  2. 由 JavaScript 创建 XMLHttpRequest 对象
  3. XMLHttpRequest 对象向 web 服务器发送http请求
  4. 服务器处理该请求
  5. 服务器将响应发送回网页
  6. 由 JavaScript 读取响应
  7. 由 JavaScript 执行正确的动作(比如更新页面)

AJAX 在这个过程中相当于是服务员,用户点好菜,由服务员把菜单交给厨师,厨师做好菜,由服务员把菜送到用户的餐桌上。

同步与异步

浏览器如果直接向服务器请求数据的话,在请求过程中,你是不能对页面进行其他操作的,这叫同步请求,而把请求数据这个活外包给 AJAX 后,在请求过程中,用户还是可以对页面进行其他操作,这就是我们的异步请求了

XML

XML被用来传输和存储数据,随着时间的推移和技术的进步,JSON 由于其简洁性和易用性,逐渐成为 AJAX 和其他 web 技术中的首选数据交换格式。现在,许多现代的 AJAX 实现和框架(例如 jQuery 和 Axios)都支持 JSON 数据格式,而不是 XML。在 AJAX 最初被提出的时候(大约 2004 年),JSON(2009年被列入ES5标准) 还没有像现在这样被广泛接受和应用。XML 作为一种成熟的数据格式,已经有了很多处理和解析的工具和技术。

music_list.xml

JSON

JSON 是一种存储和交换数据的语法

JSON 是一种轻量级的数据交换格式

在 JSON 中,键必须是字符串,由双引号包围:

{"name":"Bill Gates" }//JSON

在 JavaScript 中,键可以是字符串、数字或标识符名称:

{name:"Bill Gates" }//JavaScript

-交换数据

当数据在浏览器与服务器之间进行交换时,这些数据只能是文本。

JSON 属于文本,并且我们能够把任何 JavaScript 对象转换为 JSON,然后将 JSON 发送到服务器。

我们也能把从服务器接收到的任何 JSON 转换为 JavaScript 对象。

以这样的方式,我们能够把数据作为 JavaScript 对象来处理,无需复杂的解析和转译。

-为什么使用 JSON?

因为 JSON 格式仅仅是文本,它能够轻松地在服务器浏览器之间传输,并用作任何编程语言的数据格式。

JavaScript 提供內建函数把以 JSON 格式写的字符串转换为原生 JavaScript 对象:

JSON.parse()

因此,如果您以 JSON 格式从服务器接收数据,那么您可以像任何其他 JavaScript 对象那样使用它。

JSON 与 XML 的差异在于:

  • JSON 不使用标签
  • JSON 更短
  • JSON 的读写速度更快
  • JSON 可使用数组

最大的不同在于:

XML 必须使用 XML 解析器进行解析。而 JSON 可通过标准的 JavaScript 函数进行解析。

为什么 JSON 比 XML 更好?

  • XML 比 JSON 更难解析。
  • JSON 被解析为可供使用的 JavaScript 对象。

对于 AJAX 应用程序,JSON 比 XML 更快更易用:

使用 XML

  • 读取 XML 文档
  • 使用 XML DOM 遍历文档
  • 提取变量中存储的值

使用 JSON

  • 读取 JSON 字符串
  • JSON.Parse JSON 字符串

二、XMLHttpRequest 对象

1. 创建 XMLHttpRequest 对象

在 AJAX 中,XMLHttpRequest 对象是用来与服务器进行数据交换的,是AJAX的基石。其创建如下所示:

var httpRequest = new XMLHttpRequest();

为了保证浏览器的兼容性,我们可以用以下方式来创建。

if (window.XMLHttpRequest) {
  // Mozilla,Safari,IE7+ 等浏览器适用
  httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
  // IE 6 或者更老的浏览器适用
  httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
} 

2.向服务器发送请求

在步骤一中我们已经创建了用于服务器交换数据的 XMLHttpRequest 对象,要向服务器发送请求,我们需要调用该对象中的 open 和 send 方法。

其使用如下:

// 规定发送请求的一些要求
httpRequest.open("method", "url", async);
// 将请求发送到服务器
httpRequest.send();
方法描述
open(method, url, async)规定请求的类型
• method:请求的类型:GET 还是 POST
• url:服务器(文件)位置
• async:true(异步)或 false(同步)
send()向服务器发送请求(用于 GET)
send(string)向服务器发送请求(用于 POST)

GET 还是 POST?

GET 比 POST 更简单更快,可用于大多数情况下。

  • GET通常用于请求数据
  • POST用于提交数据

不过,请在以下情况始终使用 POST:

  • 缓存文件不是选项(更新服务器上的文件或数据库)
  • 向服务器发送大量数据(POST 无大小限制)
  • 发送用户输入(可包含未知字符),POST 比 GET 更强大更安全

url - 服务器上的文件

open() 方法的 url 参数,是服务器上文件的地址:

xhttp.open("GET", "ajax_test.asp", true);

该文件可以是任何类型的文件,如 .txt 和 .xml,或服务器脚本文件,如 .asp 和 .php(它们可以在发送回响应之前在服务器执行操作)。

异步 - true 还是 false?

如需异步发送请求,open() 方法的 async 参数必须设置为 true

xhttp.open("GET", "ajax_test.asp", true);

发送异步请求对 web 开发人员来说是一个巨大的进步。服务器上执行的许多任务都非常耗时。在 AJAX 之前,此操作可能会导致应用程序挂起或停止。

通过异步发送,JavaScript 不必等待服务器响应,而是可以:

  • 在等待服务器响应时执行其他脚本
  • 当响应就绪时处理响应

同步请求

如需执行同步的请求,请把 open() 方法中的第三个参数设置为 false

xhttp.open("GET", "ajax_info.txt", false);

有时 async = false 用于快速测试。你也会在更老的 JavaScript 代码中看到同步请求。

由于代码将等待服务器完成,所以不需要 onreadystatechange 函数:

我们不推荐同步的 XMLHttpRequest (async = false),因为 JavaScript 将停止执行直到服务器响应就绪。如果服务器繁忙或缓慢,应用程序将挂起或停止。

同步 XMLHttpRequest 正在从 Web 标准中移除,但是这个过程可能需要很多年。

现代开发工具被鼓励对使用同步请求做出警告,并且当这种情况发生时,可能会抛出 InvalidAccessError 异常。

3.服务器响应状态

当 httpRequest.readyState 为 4 并且 httpRequest.status 等于 200 时,说明数据请求成功,其使用如下:

httpRequest.onreadystatechange = function () {
  if (httpRequest.readyState == 4 && httpRequest.status == 200) {
    // 请求成功执行的代码
  } else {
    // 请求失败执行的代码
  }
};

<!DOCTYPE html>
<html>
  <style>
    table,
    th,
    td {
      border: 1px solid black;
      border-collapse: collapse;
    }
    th,
    td {
      padding: 5px;
    }
  </style>
  <body>
    <h1>XMLHttpRequest 对象</h1>

    <button type="button" onclick="loadDoc()">获取我的音乐列表</button>
    <br /><br />
    <table id="demo"></table>

    <script>
      function loadDoc() {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
          if (this.readyState == 4 && this.status == 200) {
            myFunction(this);
          }
        };
        xhttp.open("GET", "music_list.xml", true);
        xhttp.send();
      }
      //用于处理XML数据并构建表格
      function myFunction(xml) {
        var i;
        var xmlDoc = xml.responseXML; //从XMLHttpRequest对象获取响应的XML数据,并将其赋值给xmlDoc变量
        var table =
          "<tr><th>曲目</th><th>艺术家</th><th>专辑</th><th>国家</th><th>公司</th><th>年份</th></tr>"; //初始化一个字符串变量table,用于构建表格
        var x = xmlDoc.getElementsByTagName("TRACK"); // 从xmlDoc中获取所有标签名为“TRACK”的元素,并将结果赋值给x变量
        for (i = 0; i < x.length; i++) {
          table +=
            // 将当前“ARTIST”元素的第一个子节点的值(即文本内容)添加到txt字符串中,并添加一个换行符,nodeValue返回节点的值
            "<tr><td>" +
            x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue +
            "</td><td>" +
            x[i].getElementsByTagName("ARTIST")[0].childNodes[0].nodeValue +
            "</td><td>" +
            x[i].getElementsByTagName("ALBUM")[0].childNodes[0].nodeValue +
            "</td><td>" +
            x[i].getElementsByTagName("COUNTRY")[0].childNodes[0].nodeValue +
            "</td><td>" +
            x[i].getElementsByTagName("COMPANY")[0].childNodes[0].nodeValue +
            "</td><td>" +
            x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue +
            "</td></tr>"; //在table字符串后追加一个新的表格行和数据
        }
        document.getElementById("demo").innerHTML = table; //将ID为“demo”的元素的内容设置为table字符串,从而显示表格
      }
    </script>
  </body>
</html>

三、XMLHttpRequest 对象属性

1.onreadystatechange

我们使用 HTTP 请求数据后,请求是否成功,会反馈给我们相应的请求状态。我们使用 onreadystatechange 去检查响应的状态,onreadystatechange是一个事件处理器,它在 XMLHttpRequest 对象的 readyState 属性发生变化时调用的函数。(它是一个回调函数)

2.readyState

readyState 的值代表请求的状态,当XMLHttpRequest对象把HTTP请求发送到服务器端时,会经历若干状态,一直等待直到请求被处理,然后再接收一个响应。

它的取值有以下几种:

状态描述
0UNSENT代理被创建,但尚未调用 open() 方法。初始化请求
1OPENEDopen() 方法已经被调用。已与服务器建立连接
2HEADERS_RECEIVEDsend() 方法已经被调用,并且头部和状态已经可获得。请求被接受
3LOADING下载中;responseText 属性已经包含部分数据。请求中
4DONE下载操作已完成,可以在客户端使用了

3.status

status 的值是一个无符号短整型 返回了 **XMLHttpRequest 响应中的数字状态码**。在请求完成前,status 的值为 0。值得注意的是,如果 XMLHttpRequest 出错,浏览器返回的 status 也为 0。status 码是标准的 HTTP status codes。举个例子,status 200 代表一个成功的请求。如果服务器响应中没有明确指定 status 码,XMLHttpRequest.status 将会默认为 200

HTTP 响应状态码用来表明特定 HTTP 请求是否成功完成。 响应被归为以下五大类:

  1. 信息响应 (100199)
  2. 成功响应 (200299)
  3. 重定向消息 (300399)
    1. 304 Not Modified 说明无需再次传输请求的内容,也就是说可以使用缓存的内容,使用ctrl+F5强制刷新可再次200
  4. 客户端错误响应 (400499)//常见的404: 未找到页面
  5. 服务端错误响应 (500599)
var xhr = new XMLHttpRequest();
console.log("UNSENT", xhr.status);

xhr.open("GET", "/server", true);
console.log("OPENED", xhr.status);

xhr.onprogress = function () {
  console.log("LOADING", xhr.status);
};

xhr.onload = function () {
  console.log("DONE", xhr.status);
};

xhr.send(null);

/**
 * 输出如下:
 *
 * UNSENT(未发送)0
 * OPENED(已打开)0
 * LOADING(载入中)200
 * DONE(完成)200
 */

4.statusText

返回了XMLHttpRequest 请求中由服务器返回的一个[DOMString](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String) 类型的文本信息,这则信息中也包含了响应的数字状态码。这个属性包含了返回状态对应的文本信息,例如"OK"或是"Not Found"。如果请求的状态[readyState](https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState)的值为"UNSENT"或者"OPENED",则这个属性的值将会是一个空字符串。如果服务器未明确指定一个状态文本信息,则statusText的值将会被自动赋值为"OK"。

var xhr = new XMLHttpRequest();
console.log("0 UNSENT", xhr.statusText);

xhr.open("GET", "/server", true);
console.log("1 OPENED", xhr.statusText);

xhr.onprogress = function () {
  console.log("3 LOADING", xhr.statusText);
};

xhr.onload = function () {
  console.log("4 DONE", xhr.statusText);
};

xhr.send(null);

/**
 * 输出如下:
 *
 * 0 UNSENT
 * 1 OPENED
 * 3 LOADING OK
 * 4 DONE OK
 */

5.onload

使用 XMLHttpRequest 对象时,您可以定义一个回调函数,以便在请求收到答复时执行(readyState==4

请在 XMLHttpRequest 对象的 onload 属性中定义该函数:

6.responseText

以字符串形式返回响应数据。

document.getElementById("demo").innerHTML = xhttp.responseText;

7.responseXML

XML HttpRequest 对象有一个內建的 XML 解析器。

ResponseXML 属性以 XML DOM 对象返回服务器响应。

使用此属性,您可以把响应解析为 XML DOM 对象:

music_list.xml

<!DOCTYPE html>
<html>
  <body>
    <h1>XMLHttpRequest 对象</h1>

    <p id="demo"></p>

    <script>
      var xhttp, xmlDoc, txt, x, i;
      xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          xmlDoc = this.responseXML;
          txt = "";
          x = xmlDoc.getElementsByTagName("ARTIST");//获取标签为ASTIST的集合
          for (i = 0; i < x.length; i++) {
            txt = txt + x[i].childNodes[0].nodeValue + "<br>";//nodeValue返回节点的值
          }
          document.getElementById("demo").innerHTML = txt;
        }
      };
      xhttp.open("GET", "music_list.xml", true);
      xhttp.send();
    </script>
  </body>
</html>

四、XMLHttpRequest 对象方法

getAllResponseHeaders() 方法

返回资源的所有头信息,如长度,服务器类型,内容类型,最后修改等

<!DOCTYPE html>
<html>
  <body>
    <h1>XMLHttpRequest 对象</h1>

    <p>
      getAllResponseHeaders()
      函数返回资源的所有头信息,如长度,服务器类型,内容类型,最后修改等:
    </p>

    <p id="demo"></p>

    <script>
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          document.getElementById("demo").innerHTML =
            this.getAllResponseHeaders();
        }
      };
      xhttp.open("GET", "ajax_info.txt", true);
      xhttp.send();
    </script>
  </body>
</html>

getResponseHeader() 方法

返回资源的特定头信息,如长度,服务器类型,内容类型,最后修改等

<!DOCTYPE html>
<html>
  <body>
    <h1>XMLHttpRequest 对象</h1>

    <p>
      getResponseHeader()
      函数返回资源的特定头信息,如长度,服务器类型,内容类型,最后修改等:
    </p>

    <p>最后修改时间:<span id="demo"></span></p>

    <script>
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          document.getElementById("demo").innerHTML =
            this.getResponseHeader("Last-Modified");
        }
      };
      xhttp.open("GET", "ajax_info.txt", true);
      xhttp.send();
    </script>
  </body>
</html>

五、jsonserver使用

1.安装node环境

PixPin_2024-03-11_17-11-44.jpg

输入node检查是否安装成功

PixPin_2024-03-11_17-12-09.jpg

2.安装 json-server

npm i -g json-server 安装

安装完后使用json-server 查看是否安装成功

Untitled

如果安装失败,这是因为你的系统禁止使用,解决方式也很简单:

  1. 我们使用管理员方式打开 Power Shell。
  2. 输入Get-ExecutionPolicy,可以查看到当前的策略。
  3. 输入Set-ExecutionPolicy RemoteSigned,设置当前的策略为 RemoteSigned。
  4. 输入y后在运行就可以了。

3.使用

json-server --watch db.json

PixPin_2024-03-11_17-14-07.jpg

<!DOCTYPE html>
<html>
  <body>
    <div id="demo">
      <h1>XMLHttpRequest 对象</h1>
      <button type="button" onclick="loadDoc()">修改内容</button>
    </div>

    <script>
      function loadDoc() {
        var xhttp = new XMLHttpRequest();
        xhttp.onload = function () {
            document.getElementById("demo").innerHTML = this.responseText;
        };
        xhttp.open("GET", "http://localhost:3000/posts", true); 
        xhttp.send(); 
      }
    </script>
  </body>
</html>
{
  "posts": [
    {
      "id": 1,
      "title": "json-server",
      "author": "typicode"
    }
  ],
  "comments": [
    {
      "id": 1,
      "body": "some comment",
      "postId": 1
    }
  ],
  "profile": {
    "name": "typicode"
  }
}

六、使用JSONPlaceHolder的实例

👉 JSONPlaceHolder是一个**免费的HTTP请求假数据接口**

使用此地址可以获取到文章列表假数据,共100条,有帖子ID、发贴人ID、标题、内容

jsonplaceholder.typicode.com/posts

PixPin_2024-03-11_17-15-29.jpg

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      span {
        display: flex;
      }
    </style>
  </head>
  <body>
    <div id="demo"></div>
    <script>
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {
        if (this.readyState == 4) {
          var response = JSON.parse(this.responseText);
          console.log(response);
          response.forEach((element) => {
            let userid = document.createElement("span");
            let usertitle = document.createElement("span");
            let userbody = document.createElement("span");
            userid.textContent = element.id; 
            usertitle.textContent = element.title;
            userbody.textContent = element.body;
            demo.appendChild(userid);
            demo.appendChild(usertitle);
            demo.appendChild(userbody);
          });
        }
      };
      xhttp.open("GET", "https://jsonplaceholder.typicode.com/posts", true);
      xhttp.send();
    </script>
  </body>
</html>

PixPin_2024-03-11_17-16-07.jpg