JavaScript Ajax

AJAX 是 Asynchronous JavaScript And XML(异步JavaScript和XML)的缩写。AJAX 让网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。

AJAX 是 Asynchronous JavaScript And XML(异步 JavaScript 和 XML)的缩写。AJAX 让网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。

AJAX 不是一种编程语言,也不是一种新技术。AJAX 只是使用以下组合:

  • 浏览器内置 XMLHttpRequest 对象(从 Web 服务器请求数据)
  • JavaScript 和 HTML DOM(显示或使用数据)

AJAX 是一个误导性的名称。AJAX 应用程序可能使用 XML 来传输数据,但将数据作为纯文本或 JSON 文本传输也同样常见。

AJAX 允许通过在后台与 Web 服务器交换数据来异步更新网页。这意味着可以更新网页的部分内容,而无需重新加载整个页面。

所有现代浏览器都支持 XMLHttpRequest 对象。

AJAX 的工作原理

下面是一个典型的 AJAX 请求的发生过程:

  1. 由网页中的事件触发请求(比如页面加载完毕,按钮被点击)
  2. 由 JavaScript 创建一个 XMLHttpRequest 对象
  3. XMLHttpRequest 对象向 Web 服务器发送异步请求
  4. 服务器处理请求
  5. 服务器向网页发送响应
  6. 响应被 JavaScript 读取
  7. 由 JavaScript 执行相应的操作(如页面更新)

创建一个 XMLHttpRequest 对象

所有现代浏览器(Chrome、Firefox、IE、Edge、Safari、Opera)都内置了 XMLHttpRequest 对象。

创建 XMLHttpRequest 对象的语法:

variable = new XMLHttpRequest();

绑定请求完成的回调函数

当 XMLHttpRequest 对象状态发生变化的时候,可以针对不同的状态变化事件绑定相应的处理函数。

为请求完成事件绑定处理函数,处理函数中可以处理请求返回的数据,比如将数据显示到网页等。

xhttp.onload = function () {
  // What do do when the response is ready
};

XMLHttpRequest 对象的 onload 绑定请求完成的处理函数。

发送请求

使用 XMLHttpRequest 对象的 open()send() 方法,向服务器发送请求:

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

完整代码框架

// Create an XMLHttpRequest object
const xhttp = new XMLHttpRequest();

// Define a callback function
xhttp.onload = function () {
  // Here you can use the Data
};

// Send a request
xhttp.open("GET", "ajax_info.txt");
xhttp.send();

AJAX 请求函数

如果网站中有多个 AJAX 任务,则应创建一个函数来执行 AJAX 请求。该函数有两个参数,一个是服务器的 url, 一个是请求成功后的回调函数。

一个公共的 Ajax 请求函数:

loadDoc("url-1", myFunction1);

loadDoc("url-2", myFunction2);

function loadDoc(url, cFunction) {
  const xhttp = new XMLHttpRequest();
  xhttp.onload = function () {
    cFunction(this);
  };
  xhttp.open("GET", url);
  xhttp.send();
}

function myFunction1(xhttp) {
  // action goes here
}
function myFunction2(xhttp) {
  // action goes here
}

onreadystatechange 属性

XMLHttpRequest 对象的 readyState 属性保存了请求的状态,onreadystatechange 属性定义了当 readyState 更改时要执行的回调函数。

readyState 有 5 个状态:

  • 0: 请求还未初始化
  • 1: 与服务器建立了连接
  • 2: 请求接收
  • 3: 处理请求中
  • 4: 请求结束,响应数据返回

status 属性和 statusText 属性保存请求的 HTTP 状态码和状态码消息。

每次 readyState 更改时都会调用 onreadystatechange 函数。

readyState4 且状态码为 200 时,响应准备就绪:

function loadDoc() {
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("demo").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "ajax_info.txt");
  xhttp.send();
}

向服务器发送请求

要向服务器发送请求,我们使用 XMLHttpRequest 对象的 open()send() 方法:

xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();

open(method, url, async) 用于定义请求方式,接收 3 个参数:

  • method: HTTP 请求方法,比如 GET 或 POST
  • url: 服务器文件 URL 或者 API url
  • async: 是否异步:true (异步), false (同步)

open() 方法的 async 参数应设置为 true。如果设置为 false,则可能在请求期间将浏览器挂起,知道请求完成。

send() 方法用于发送请求到服务器,可以接收一个参数,但不是必须的。参数指定要发送到服务器的数据内容。

GET 还是 POST?

GETPOST 更简单、更快 ,并且可以在大多数情况下使用。

但是,在以下情况下始终使用 POST 请求:

  • 更新服务器上的文件或数据库。
  • 向服务器发送大量数据(POST 没有大小限制)。
  • 发送用户输入(可能包含未知字符),POST 比 GET 更健壮和安全。

GET 请求

一个简单的 GET 请求:

xhttp.open("GET", "demo_get.asp");
xhttp.send();

在上面的例子中,你可能会得到一个浏览器缓存的结果。为避免这种情况,请向 URL 添加随机参数:

xhttp.open("GET", "demo_get.asp?t=" + Math.random());
xhttp.send();

如果要使用 GET 方法发送信息,请将信息添加到 URL:

xhttp.open("GET", "demo_get2.asp?fname=Henry&lname=Ford");
xhttp.send();

POST 请求

一个简单的 POST 请求:

xhttp.open("POST", "demo_post.asp");
xhttp.send();

要像 HTML 表单一样提交数据,请使用 setRequestHeader() 设置请求头,并在 send() 方法中指定要发送的数据。

xhttp.open("POST", "ajax_test.asp");
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("fname=Henry&lname=Ford");

同步请求

要执行同步请求,请将 open() 方法中的第三个参数更改为 false

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

有时 async = false 用于快速测试。您还会在较旧的 JavaScript 代码中找到同步请求。

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

xhttp.open("GET", "ajax_info.txt", false);
xhttp.send();
document.getElementById("demo").innerHTML = xhttp.responseText;

不建议使用同步,因为 JavaScript 将停止执行,直到服务器响应准备就绪。如果服务器繁忙或缓慢,应用程序将挂起或停止。

服务器响应属性

responseTextresponseXML 用于获取服务器相应内容。

responseText 属性

responseText 属性将服务器响应作为字符串返回,您可以直接使用它:

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

responseXML 属性

XMLHttpRequest 对象有一个内置的 XML 解析器,responseXML 属性将服务器响应作为 XML DOM 对象返回。

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

请求文件 cd_catalog.xml 并解析响应:

const xmlDoc = xhttp.responseXML;
const x = xmlDoc.getElementsByTagName("ARTIST");

let txt = "";
for (let i = 0; i < x.length; i++) {
  txt += x[i].childNodes[0].nodeValue + "<br>";
}
document.getElementById("demo").innerHTML = txt;

xhttp.open("GET", "cd_catalog.xml");
xhttp.send();

服务器响应方法

getResponseHeader()getAllResponseHeaders() 用于获取服务器响应消息头的信息。

getAllResponseHeaders() 方法

getAllResponseHeaders() 方法从服务器响应返回所有消息头信息。

const xhttp = new XMLHttpRequest();
xhttp.onload = function () {
  document.getElementById("demo").innerHTML = this.getAllResponseHeaders();
};
xhttp.open("GET", "ajax_info.txt");
xhttp.send();

getResponseHeader() 方法

getResponseHeader() 方法从服务器响应中返回指定的消息头信息。

const xhttp = new XMLHttpRequest();
xhttp.onload = function () {
  document.getElementById("demo").innerHTML = this.getResponseHeader("Last-Modified");
};
xhttp.open("GET", "ajax_info.txt");
xhttp.send();

跨域访问

出于安全原因,现代浏览器不允许跨域访问。这意味着网页和它尝试加载的 XML 文件必须位于同一服务器上。

如果您想在您自己的网页之一上使用上面的示例,您加载的 XML 文件必须位于您自己的服务器上。

当然,通过服务器响应消息头的设置,可以实现请求的跨域访问,不过这是另外一个课题,在其他的课程中我们会涉及到。

现代浏览器 Fetch API

现代浏览器可以使用 Fetch API 代替 XMLHttpRequest 对象。

Fetch API 接口允许 Web 浏览器向 Web 服务器发出异步 HTTP 请求。

相对于 XMLHttpRequest 对象,Fetch 可以以更简单的方式执行相同的操作。