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 必须三件套:contentType 设 application/json、data 用 JSON.stringify 转、dataType 设 json 期望返回。
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
- API 设计:
fetch是原生 Promise 风格,更现代;$.ajax是 jQuery 自家 deferred,老但成熟。 - 错误处理:
fetch4xx/5xx 不报错(要手动判res.ok);$.ajax自动进 error 回调——后者更符合直觉。 - JSON 解析:
fetch要手动await res.json();$.ajax设dataType:json自动解析。 - 超时:
fetch没原生超时(要包 Promise.race);$.ajax一个timeout参数搞定。 - 体积:
fetch是浏览器内置,零成本;$.ajax要引整个 jQuery。
结论:新项目用 fetch 或 axios;维护老代码遇到 $.ajax,要能看懂、能改。两者都要会。
小结
jQuery AJAX 的"五件套":$.get、$.post、$.ajax、.serialize()、.load()。会这五个 + Promise 风格 + 错误处理,就足以读懂任何老 jQuery 项目里的请求逻辑。下一篇看 jQuery 的设计精髓——链式调用。
← 上一篇 jQuery 动画效果
下一篇 jQuery 链式调用 →