AJAX 是什么?

AJAX 是什么?

5月 2, 2022
JavaScript, HTTP, Frontend, 计算机网络, 浏览器

这个问题既熟悉又有点陌生,先看概念。AJAX 是 Asynchronous Javavascript XML 的缩写,即异步 JavaScript 和 XML。使用 AJAX 技术可以在无需重新加载整个网页的情况下,能够更新部分网页,从而给带来更好的用户体验。另外 AJAX 不仅使用 XML,实际上由于 JSON 结构的易读和轻量反而更受欢迎。

AJAX 不是一种单一的技术,而是利用了一系列相关的技术:

  1. 使用 CSS 和 HTML 来表示信息。
  2. 使用 DOM 模型来交互和动态显示。
  3. 使用 XMLHttpRequest 或 Fetch API 来和服务端进行异步通信。
  4. 使用 JavaScript 来操作 DOM 模型。

你可能发现,上面第 3 条的技术比如 Fetch API 是近几年的技术,而 XMLHttpRequest 才是浏览器传统网络请求技术,故之所以一开始对 AJAX 又陌生,也是因为 AJAX 的概念是在不断更新的,其涵盖的范围在不断扩大。

XMLHttpRequest #

实现传统 AJAX 的核心是 XMLHttpRequest 对象,该对象为客户端提供了在客户端和服务器之间传输数据的功能。

使用方法 #

初始化 #

创建一个 XMLHttpRequest 对象:

let xhr = new XMLHttpRequest()

建立连接 #

使用 open() 方法建立连接:

open(method, url)
open(method, url, async)
open(method, url, async, user)
open(method, url, async, user, password)
  • method :表示请求使用的方法,比如 GETPOST
  • url :表示请求的服务器地址。
  • async :可选,表示是否异步执行,默认为 true
  • user :可选,
  • password :可选。

发起请求 #

使用 send() 方法向服务器发送数据:

send()
send(body)

如果不传 body 参数,默认就是 null。

响应处理 #

The readystatechange event is fired when the readyState attribute of a document has changed.

XHR 提供了 readystatechange 事件用来监听 xhr.readyState 属性发生变化时触发。xhr.readyState 的枚举如下:

ValueStateDescription
0UNSENTClient has been created. open() not called yet.
1OPENEDopen() has been called.
2HEADERS_RECEIVEDsend() has been called, and headers and status are available.
3LOADINGDownloading; responseText holds partial data.
4DONEThe operation is complete.

除了 readystatechange 事件,XMLHttpRequest 也支持一系列其他的事件,可自行查阅文档

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

//也可以使用事件处理器 onload
xhr.onload = function() {
  if (xhr.status != 200) { // 分析响应的 HTTP 状态
    alert(`Error ${xhr.status}: ${xhr.statusText}`); // 例如 404: Not Found
  } else { // 显示结果
    alert(`Done, got ${xhr.response.length} bytes`); // response 是服务器响应
  }
};

readyState 变为 Done 时,就说明收到了响应,于是进行回调,也是通过此类回调函数的机制实现了异步处理。

嫌麻烦?上 jQuery #

如果上面一系列的步骤你还是嫌麻烦,上古的 jQuery 也提供了 jQuery.ajax() 实现对 XHR 的封装。

$("button").click(function(){
  $.ajax({url:"demo_test.txt",success:function(result){
    $("#div1").html(result);
  }});
});

回调地狱 #

事件回调机制的形式在实际的项目中可能会导致“回调地狱”的情况,处理 error 时需要格外注意。

callback hell

Fetch #

The global fetch() method starts the process of fetching a resource from the network, returning a promise which is fulfilled once the response is available.

现在浏览器中的应用更多使用的可能是 Fetch API,它提供了几乎和 XMLHttpRequest 相同的功能,但被设计成更具可拓展性和高效性。

浏览器全局函数 fetch() 用于请求一个网络资源,并通过 promise 异步的形式返回 response 对象,而且可以简化成 async/await 形式,更加符合现代前端技术的设计哲学。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Example</title>
        <script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"
        integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI="
        crossorigin="anonymous"></script>
    </head>
    <body>
        <div id="root">
            <button type="button" onclick='request();'>请求</button>
            <br />
            <div id="output"></div>
        </div>
    </body>
    <script>
        async function request(params) {
            let response = await fetch("https://httpbin.org/get");
            if (response.ok) {
                let resp = await response.json();
                output(JSON.stringify(resp));
            } else {
                output("HTTP-Error: " + response.status);
            }
        }
        function output(msg) {
            $("#output").append("<p>" + msg + "</p>");
        }
    </script>
</html>

很多前端项目专门封装的网络层可能会采用以下的形式:

const data = { username: 'example' };

fetch('https://example.com/profile', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
  console.log('Success:', data);
})
.catch((error) => {
  console.error('Error:', error);
});

跨域问题 #

默认情况下,Ajax 要满足浏览器的同源策略要求,即不能跨域访问,除非客户端使用 CORS 标准进行请求,我前面已经在 跨域相关问题 里介绍了其使用方法,只有符合了请求相关规范,并在服务器同意的情况下才能发起跨域访问。

参考 #

https://juejin.cn/post/6997784981816737800

https://zh.javascript.info/xmlhttprequest

本文共 1247 字,上次修改于 Jul 9, 2024,以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

相关文章

» WebSocket 是什么?

» 浏览器中的 HTTP 缓存使用策略

» 浏览器的事件机制

» HTTP/2 概览

» HTTPS 的 SSL/TLS 协议