jQuery AJAX

在原生 fetch 出现之前,jQuery 的 $.ajax 是发 HTTP 请求的事实标准——它把丑陋的 XMLHttpRequest 封装成了优雅的 API,自动处理 JSON 解析、跨域、错误。无数老项目里你都能看到它的身影,会读会写是必修课。

1. 简写方法:$.get / $.post / $.getJSON

日常 80% 的请求用这三个简写方法就够了。它们的本质都是 $.ajax 的预设包装,写起来更短。

// $.get:最简 GET 请求
$.get("/api/users", function (data) {
  console.log("收到:", data);
});

// 带查询参数
$.get("/api/users", { page: 1, size: 10 }, function (data) {
  console.log(data);
});

// 指定期望的返回类型:json / html / xml / text / script
$.get("/api/users", { id: 1 }, function (data) {
  // data 已自动解析成 JS 对象
  console.log(data.name);
}, "json");

// $.post:最简 POST 请求(默认表单格式)
$.post("/api/login", { user: "tom", pass: "123" }, function (res) {
  console.log("登录结果:", res);
});

// $.getJSON:专门拿 JSON
$.getJSON("/api/users/1", function (user) {
  console.log(user.name);
});

注意 post 默认发的是表单格式application/x-www-form-urlencoded),适合传统表单提交。如果要发 JSON 给现代 API,要用完整版 $.ajax 并显式设 contentType

2. 完整版:$.ajax

当简写方法不够用时(自定义头、跨域、超时、错误处理),上完整版 $.ajax。它把所有配置统一在一个对象里,是老项目最常见的写法。

// $.ajax:完整版,可配置一切
$.ajax({
  url: "/api/login",
  method: "POST",                // 或 type: "POST",两者等价
  contentType: "application/json",  // 发 JSON 时必须设
  data: JSON.stringify({ user: "tom", pass: "123" }),
  dataType: "json",              // 期望返回类型,jQuery 自动解析
  timeout: 10000,                // 10 秒超时
  beforeSend: function (xhr) {
    xhr.setRequestHeader("Authorization", "Bearer abc123");
  },
  success: function (res) {
    console.log("成功", res);
  },
  error: function (xhr, status, err) {
    console.log("失败", xhr.status, err);
  },
  complete: function () {
    console.log("不管成功失败都执行");
  }
});

// 常用配置项速查
// url          请求地址
// method/type  GET/POST/PUT/DELETE...
// data         发送的数据(对象或字符串)
// contentType  发送的内容类型
// dataType     期望返回类型(json/html/xml/script/text)
// headers      自定义请求头
// timeout      超时毫秒数
// async        是否异步(默认 true,不要改 false!)
// cache        是否缓存(默认 true,script/jsonp 默认 false)

最常见的坑:发 JSON 时忘了设 contentType,结果服务端按表单格式解析,怎么都拿不到数据。记住——发 JSON 必须三件套:contentTypeapplication/jsondataJSON.stringify 转、dataTypejson 期望返回。

3. Promise 风格(jQuery 3+)

从 jQuery 1.5 起,$.ajax 返回的是一个 Promise-like 对象(deferred),可以链式 .then()。jQuery 3 后完全兼容原生 Promise 规范,async/await 也能用。

// jQuery 3+ 的 $.ajax 返回 Promise,可以链式 then
$.ajax({ url: "/api/users/1", dataType: "json" })
  .then(function (user) {
    console.log("拿到用户:", user);
    return $.ajax({ url: "/api/orders?uid=" + user.id });
  })
  .then(function (orders) {
    console.log("拿到订单:", orders);
  })
  .catch(function (err) {
    console.log("出错了:", err);
  });

// 解构回调地狱:旧写法(嵌套)
$.ajax({
  url: "/api/users/1",
  success: function (user) {
    $.ajax({
      url: "/api/orders?uid=" + user.id,
      success: function (orders) {
        $.ajax({
          url: "/api/items?oid=" + orders[0].id,
          success: function (items) {
            // 三层嵌套,越写越丑...
          }
        });
      }
    });
  }
});

// Promise 写法明显更清爽,新版首选

对比看:嵌套回调(左)越写越深,可读性极差;Promise 链(右)扁平清晰。维护老代码时,遇到嵌套两层以上的回调,强烈建议改写成 Promise。

4. 表单提交:serialize

表单是 AJAX 最常见的应用场景。.serialize() 一行就能收集所有字段,省去手动取值的麻烦。

// .serialize():把表单里所有命名字段拼成查询字符串
// name=tom&pass=123&remember=1
$("#form").serialize();

// .serializeArray():返回数组,每项是 { name, value }
const arr = $("#form").serializeArray();
// [{ name: "user", value: "tom" }, { name: "pass", value: "123" }]

// 经典:表单提交 + AJAX
$("#form").on("submit", function (e) {
  e.preventDefault();           // 阻止默认提交
  $.ajax({
    url: $(this).attr("action"),
    method: $(this).attr("method") || "POST",
    data: $(this).serialize(),  // 一行收集所有字段
    success: function (res) {
      alert("提交成功");
    }
  });
});

// 发 JSON(给现代 API 用)
$.ajax({
  url: "/api/user",
  method: "POST",
  contentType: "application/json",
  data: JSON.stringify({ user: "tom", pass: "123" })
});

关键点:用 e.preventDefault() 阻止表单默认提交;用 $(this).serialize() 收集字段;用 attr("action") 拿表单配置的地址。这套写法在十年前被复制粘贴了无数次。

5. 加载 HTML 与脚本:load / getScript

两个不太出名但很实用的方法:.load() 直接把服务端返回的 HTML 塞进元素;$.getScript() 动态加载并执行 JS 文件。

// .load():把服务端返回的 HTML 直接塞进元素
$("#result").load("/api/profile");           // 整个 HTML 塞进去

// 只取返回 HTML 的一部分(选择器过滤)
$("#result").load("/api/profile .avatar");   // 只要 .avatar 部分

// 带回调
$("#result").load("/api/profile", function () {
  console.log("加载完了");
});

// $.getScript():动态加载并执行 JS 文件
$.getScript("/js/analytics.js", function () {
  console.log("脚本加载并执行了");
  // 此时 analytics.js 里定义的函数已可用
});

.load() 配合选择器过滤url selector),可以只取返回 HTML 的一部分——做"加载某段内容到当前页"非常方便,是早期单页应用的实现方式之一。

6. 错误处理与全局事件

生产环境的 AJAX 必须处理失败。jQuery 提供了细粒度的错误信息(超时、解析错、HTTP 错误分别区分),还有全局事件用来做统一 loading。

// 错误处理的几种方式
$.ajax({
  url: "/api/users/999",
  dataType: "json"
})
.fail(function (xhr, status, err) {
  // status 可能是:"timeout"/"error"/"parsererror"/"abort"
  if (status === "timeout") {
    alert("请求超时,请重试");
  } else if (status === "parsererror") {
    console.log("服务端返回的不是合法 JSON");
  } else {
    console.log("HTTP 状态码:", xhr.status);   // 404/500 等
    console.log("响应体:", xhr.responseText);
  }
})
.always(function () {
  // 不管成功失败都执行(隐藏 loading)
  $("#loading").hide();
});

// 全局 AJAX 事件:监听所有请求(适合做全局 loading)
$(document)
  .ajaxStart(function () { $("#loading").show(); })
  .ajaxStop(function () { $("#loading").hide(); })
  .ajaxError(function (e, xhr, settings, err) {
    console.log("任何 ajax 失败都会触发");
  });

// 跨域注意事项
//  1. 同源策略:协议+域名+端口必须一致
//  2. 跨域需服务端开 CORS 头(Access-Control-Allow-Origin)
//  3. JSONP 是老办法,只支持 GET,jQuery 也支持,但已过时
//  4. 现代项目用 fetch + CORS 即可

记住几个常见错误状态timeout(超时)、parsererror(JSON 解析失败,常因服务端返回了 HTML 错误页)、error(HTTP 4xx/5xx)。跨域请求要服务端开 CORS 头,否则浏览器拦截——这是新手最常遇到的"为什么 fetch 拿不到数据"。

7. jQuery AJAX vs fetch

结论:新项目用 fetch 或 axios;维护老代码遇到 $.ajax,要能看懂、能改。两者都要会。

小结

jQuery AJAX 的"五件套":$.get$.post$.ajax.serialize().load()。会这五个 + Promise 风格 + 错误处理,就足以读懂任何老 jQuery 项目里的请求逻辑。下一篇看 jQuery 的设计精髓——链式调用

← 上一篇 jQuery 动画效果

下一篇 jQuery 链式调用

✈️💬