Skip to content

Ajax

作者:青见春山
发表于:2026-07-27
字数统计:2084 字
预计阅读7分钟

AJAX(Asynchronous JavaScript and XML)即异步 JavaScript 和 XML,用于在不刷新页面的情况下与服务器进行数据交互。

1. 特性

1.1 异步性

可以在不阻塞用户界面操作的情况下进行数据交互。

1.2 局部刷新

能够仅更新页面的特定部分,而不是整个页面重新加载。

1.3 增强用户体验

让用户感觉应用更加流畅和响应迅速。

1.4 按需交换数据

只交换页面需要的数据时,可能减少传输和重复渲染;请求过多或接口设计不当仍可能降低性能。

1.5 及时更新

可以按事件或定时请求最新数据,但 AJAX 本身不是实时推送机制;实时双向通信通常使用 WebSocket,单向推送还可使用 Server-Sent Events。

2. 使用步骤

  1. 创建 XMLHttpRequest 对象
  2. 通过 open() 初始化请求方法、URL 等参数;它不会立即建立网络连接
  3. 构建请求所需的数据内容,并通过 XMLHttpRequest 对象的 send() 方法发送给服务器端
  4. 通过 XMLHttpRequest 对象提供的 readystatechangeloadend 事件监听服务器端的通信状态
  5. 接受并处理服务端向客户端响应的数据结果
  6. 将处理结果更新到 HTML 页面中

3. 代码示例

3.1 GET 请求示例

javascript
const btn = document.getElementById("btn");
const ul = document.getElementById("list");

btn.addEventListener("click", () => {
  // 朝一个接口发请求,获取到数据展示到页面上
  const xhr = new XMLHttpRequest(); // 创建一个 ajax 实例
  xhr.open("GET", "https://example.com/api/list", true);
  xhr.send();
  xhr.onreadystatechange = () => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      const res = xhr.responseText; // 拿到后端返回的数据
      const data = JSON.parse(res); // 解析 JSON
      const movieList = data.movieList;

      for (let index = 0; index < movieList.length; index++) {
        const li = document.createElement("li");
        li.innerText = movieList[index].nm + "--" + movieList[index].star;
        ul.appendChild(li);
      }
    }
  };
});

3.2 POST 请求示例

javascript
// 本例发送 JSON,因此显式设置对应的 Content-Type
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://xxx/api/register");

xhr.addEventListener("readystatechange", () => {
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 在这里处理服务器的响应数据
    console.log(xhr.response);
  }
});

xhr.setRequestHeader("Content-Type", "application/json");

const obj = {
  username: "xxx",
  password: "xxx",
};

xhr.send(JSON.stringify(obj));

3.3 简化写法

javascript
const xhr = new XMLHttpRequest();
xhr.open("GET", "http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2");

xhr.addEventListener("loadend", () => {
  // loadend 在成功、失败或中止后都会触发,仍需检查 status 或分别监听 load/error
  if (xhr.status >= 200 && xhr.status < 300) {
    console.log(xhr.response);
  }
});

xhr.send();

3.4 旧写法 vs 新写法

javascript
// 旧写法
xhr.onreadystatechange = function () {
  if (xhr.readyState !== 4) return;
  if (xhr.status >= 200 && xhr.status < 300) {
    // 在这里处理服务器的响应数据
    console.log(xhr.responseText);
  } else {
    // 这里只处理请求完成后的 HTTP 错误,不会在中间状态重复报错
    console.log(xhr.statusText);
  }
};

// 新写法
xhr.addEventListener("readystatechange", () => {
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 在这里处理服务器的响应数据
    console.log(xhr.response);
  }
});

4. 参数说明

4.1 open()

open() 只初始化请求;真正的网络请求由 send() 启动。

语法:xhr.open(method, url, [async])

参数描述
method表示当前的请求方式,常见的有 GET、POST
url服务端地址
async布尔值,表示是否异步执行操作,默认为 true(异步)

4.2 send()

通过 XMLHttpRequest 对象的 send() 方法,将客户端页面的数据发送给服务端。

语法:xhr.send([body])body 除字符串外,还可以是 FormDataBlobArrayBufferURLSearchParamsDocument 等受支持类型;无请求体时省略或传 null

4.3 onreadystatechange

每当 readyState 实际发生变化时会触发 readystatechange。不要依赖固定触发次数;只需判断是否到达 DONE(值为 4),或按需使用 loaderroraborttimeout 等事件。

4.3.1 XMLHttpRequest 对象的三个重要属性

属性描述
onreadystatechange存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数
readyState存有 XMLHttpRequest 的状态
status200: "OK",404: 未找到页面

4.3.2 readyState 的取值(ajax 的状态)

  • 0 — xhr 刚创建
  • 1 — open 执行
  • 2 — 已接收响应状态和响应头
  • 3 — 正在接收响应体,可能已有部分数据
  • 4 — 请求操作完成(无论 HTTP 状态是否成功)

4.4 服务器响应

获取 XMLHttpRequest 响应体。

5. GET 和 POST 对比

GET 与 POST 的核心差异是 HTTP 语义,不是固定的速度或安全级别:

  • GET 用于获取资源,是安全且幂等的方法;其 URI 可能出现在历史、日志和缓存键中,不应把敏感数据放进查询串
  • POST 让目标资源处理请求内容,通常非幂等;协议允许缓存 POST 响应,但实践中需要明确的缓存配置
  • HTTP 没有规定“POST 请求体无限大”。浏览器、代理、Web 服务器和应用都可以设置大小上限;GET 的 URI 长度也常受各层实现限制
  • 是否设置 Content-Type 取决于请求体格式。发送 JSON 或表单编码文本时应设置;发送 FormData 时不要手写该头,否则容易遗漏浏览器生成的 boundary

6. FormData

模拟表单,适合用于发送包含文件上传等复杂数据的请求。

使用 FormData 可以执行以下步骤:

6.1 创建 FormData 对象

javascript
const formData = new FormData();

6.2 向 FormData 对象中添加字段

javascript
formData.append("username", "John");
formData.append("email", "john@example.com");

6.3 添加文件类型的字段

javascript
// 从文件输入框中获取选中的文件,可以根据实际情况选择获取文件的方式
const fileInput = document.getElementById("fileInput");
formData.append("file", fileInput.files[0]);

6.4 将 FormData 对象作为请求的 body

javascript
const xhr = new XMLHttpRequest();
xhr.open("POST", "/api/endpoint");
xhr.send(formData);

6.5 注意事项

  • 当使用 FormData 时,浏览器会自动设置适当的 Content-Type 头部,无需手动设置
  • FormData 也支持删除字段和追加相同字段名的多个值等操作

6.6 参考资料

FormData 对象的使用 - Web API | MDN (mozilla.org)

FormData - Web API | MDN (mozilla.org)

7. 封装 ajax

javascript
// 使用的时候直接调用,传递一个对象就可以
ajax({
  url: "", // 请求的地址
  type: "", // 请求方式
  async: "", // 是否异步
  data: "", // 携带的参数
  dataType: "", // 要不要执行 JSON.parse
  success: function () {}, // 成功以后执行的函数
});

7.1 简单封装示例

javascript
function ajax(options) {
  const xhr = new XMLHttpRequest();

  // 处理参数
  let params = "";
  if (options.data) {
    const arr = [];
    for (const key in options.data) {
      arr.push(encodeURIComponent(key) + "=" + encodeURIComponent(options.data[key]));
    }
    params = arr.join("&");
  }

  let url = options.url;
  if (options.type.toUpperCase() === "GET" && params) {
    url += "?" + params;
  }

  xhr.open(options.type, url, options.async ?? true);

  if (options.type.toUpperCase() === "POST") {
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send(params);
  } else {
    xhr.send();
  }

  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
      let res = xhr.responseText;
      if (options.dataType === "json") {
        res = JSON.parse(res);
      }
      options.success && options.success(res);
    }
  };
}

8. 使用 XMLHttpRequest 对象

  1. 获取页面上的按钮元素和列表元素
  2. 为按钮添加点击事件监听
  3. 在点击事件处理函数中:
    • 创建 XMLHttpRequest 对象用于进行 AJAX 请求
    • 配置请求方法、请求地址和异步方式
    • 发送请求
    • 监听请求状态变化
  4. 当请求状态为 4 且状态码为 200 时(表示请求成功):
    • 获取响应文本
    • 将响应文本解析为 JSON 对象
    • 通过遍历数据,创建列表项元素并添加到列表中展示

9. Fetch API(补充)

Fetch 是现代浏览器提供的原生 AJAX 替代方案,基于 Promise。

9.1 基本用法

javascript
fetch("https://api.example.com/data")
  .then((response) => {
    // Fetch 只会因网络层失败而 reject,404/500 仍会 resolve。
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return response.json();
  })
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

9.2 POST 请求

javascript
fetch("https://api.example.com/data", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ name: "John", age: 25 }),
})
  .then((response) => response.json())
  .then((data) => console.log(data));

9.3 async/await 写法

javascript
async function fetchData() {
  try {
    const response = await fetch("https://api.example.com/data");
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

9.4 Fetch 的优点

  • Promise 风格,链式调用更优雅
  • 语法简洁
  • 可以与现代 async/await 结合
  • 内置支持 FormData、Blob、JSON 等多种格式