在前端开发中,Ajax(Asynchronous JavaScript and XML)是实现 “无刷新交互” 的核心技术,尤其在后台管理系统、电商平台等场景中,Ajax 几乎是前端与后端通信的标配。尽管如今 Fetch API、Axios 等工具层出不穷,但基于 jQuery 的 Ajax 仍因兼容性好、上手简单,广泛应用于各类传统项目(如后台管理系统)。本文将从原理到实战,拆解 Ajax 的核心逻辑,封装通用请求方案,并总结高频避坑点,帮助开发者打造高可靠、易维护的 Ajax 请求体系。
一、Ajax 核心认知:不止是 “异步请求”
1. 什么是 Ajax?
Ajax 并非单一技术,而是一套组合方案:通过 JavaScript 异步发送 HTTP 请求,获取服务器数据后,通过 DOM 操作更新页面,全程无需刷新浏览器。其核心是XMLHttpRequest(XHR)对象 —— 浏览器内置的用于与服务器交互的 API,而 jQuery Ajax 本质是对 XHR 的封装,简化了底层操作。
2. Ajax 核心工作流程
无论原生 XHR 还是 jQuery Ajax,核心流程一致:
是
否
创建请求对象
配置请求参数(URL、方法、请求头)
发送请求到服务器
监听请求状态变化
请求成功?
解析响应数据并更新页面
处理错误(404/500/网络异常)
是
否
创建请求对象
配置请求参数(URL、方法、请求头)
发送请求到服务器
监听请求状态变化
请求成功?
解析响应数据并更新页面
处理错误(404/500/网络异常)
3. 原生 XHR 示例(理解底层逻辑)
先通过原生 XHR 实现一个简单的 GET 请求,理解 Ajax 的本质:
javascript
运行
// 1. 创建XHR对象 const xhr = new XMLHttpRequest(); // 2. 配置请求(方法、URL、是否异步) xhr.open('GET', '/pc/goods/list', true); // 3. 设置请求头(如携带Token) xhr.setRequestHeader('token', sessionStorage.getItem('token')); // 4. 监听状态变化 xhr.onreadystatechange = function() { // readyState=4 表示请求完成;status=200 表示响应成功 if (xhr.readyState === 4 && xhr.status === 200) { // 5. 解析响应数据(后台返回JSON格式) const res = JSON.parse(xhr.responseText); console.log('请求成功:', res); // 更新页面DOM renderGoodsList(res.data); } }; // 6. 处理错误 xhr.onerror = function() { console.error('网络异常,请求失败'); }; // 7. 发送请求 xhr.send();原生 XHR 代码冗余,且需要手动处理状态、解析数据,这也是 jQuery Ajax 被广泛使用的原因 —— 它将上述逻辑封装为简洁的 API。
二、jQuery Ajax 实战:适配后台管理系统场景
在后台管理系统(如礼盒商城后台)中,jQuery Ajax 是最常用的请求方式。以下结合实战场景,讲解核心用法和配置。
1. 基础用法:GET/POST 请求
(1)GET 请求(获取数据,如商品列表)
javascript
运行
// 获取商品列表 function getGoodsList() { $.ajax({ url: '/pc/goods/list', // 接口地址 type: 'GET', // 请求方法 data: { pageNum: 1, pageSize: 10 }, // 请求参数 headers: { 'token': sessionStorage.getItem('token') // 携带登录凭证 }, success: function(res) { // 后台统一返回格式:{ code: 1, msg: '成功', data: [] } if (res.code === 1) { renderGoodsList(res.data); // 渲染列表 } else { alert('获取列表失败:' + res.msg); } }, error: function(xhr, status, error) { // 处理请求错误(404/500/网络异常) console.error('请求失败:', status, error); alert('网络异常,请重试'); } }); }(2)POST 请求(提交数据,如删除商品)
javascript
运行
// 删除商品 function deleteGoods(goodsId) { $.ajax({ url: '/pc/goods/del', type: 'POST', data: { ids: goodsId }, // 提交删除ID contentType: 'application/x-www-form-urlencoded', // 默认编码格式 success: function(res) { if (res.code === 1) { alert('删除成功'); getGoodsList(); // 刷新列表 } else { alert('删除失败:' + res.msg); } }, error: function() { alert('删除失败,请重试'); } }); }2. 封装通用 Ajax 请求(核心实战)
在实际项目中,每个页面都写重复的 Ajax 配置会导致代码冗余、维护困难。结合后台管理系统的共性(统一的 token、统一的错误处理、统一的返回格式),封装一个通用请求函数是必做的优化。
通用请求函数封装(js/utils/api.js)
javascript
运行
/** * 通用Ajax请求函数 * @param {Object} options - 请求配置 * @param {string} options.url - 接口地址(无需写域名,已配置代理) * @param {string} [options.type='POST'] - 请求方法 * @param {Object} [options.data={}] - 请求参数 * @param {Function} options.success - 成功回调(仅处理业务成功) * @param {Function} [options.error] - 自定义错误回调(可选) */ function request(options) { // 默认配置 const defaultConfig = { type: 'POST', data: {}, headers: { 'token': sessionStorage.getItem('token'), // 统一携带token 'Content-Type': 'application/x-www-form-urlencoded' }, dataType: 'json', // 预期返回JSON格式 timeout: 10000, // 超时时间10秒 // 全局错误处理 error: function(xhr, status, error) { // 1. 处理token失效(后台返回401状态码) if (xhr.status === 401) { alert('登录已过期,请重新登录'); window.location.href = './html/auth/login.html'; return; } // 2. 处理其他错误(404/500/超时) const errorMsg = { '404': '接口不存在', '500': '服务器内部错误', 'timeout': '请求超时', 'error': '网络异常' }[status] || '请求失败'; // 优先执行自定义错误回调,否则默认提示 if (options.error) { options.error(errorMsg); } else { alert(errorMsg); } } }; // 合并用户配置与默认配置 const config = $.extend({}, defaultConfig, options); // 重写success回调:统一处理后台返回的code config.success = function(res) { // 业务成功(code=1)执行自定义success if (res.code === 1) { options.success(res.data); } else { // 业务失败(如参数错误、权限不足) alert('操作失败:' + res.msg); } }; // 发送请求 $.ajax(config); }通用函数调用示例(简化 90% 重复代码)
javascript
运行
// 1. 获取商品列表(GET请求) request({ url: '/pc/goods/list', type: 'GET', data: { pageNum: 1, pageSize: 10 }, success: function(data) { renderGoodsList(data); // 仅处理业务成功的逻辑 } }); // 2. 删除商品(POST请求) request({ url: '/pc/goods/del', data: { ids: 1001 }, success: function() { alert('删除成功'); getGoodsList(); // 刷新列表 }, error: function(msg) { // 自定义错误提示 console.error('删除失败:', msg); } });三、Ajax 高级技巧:解决实战中的核心问题
1. 请求拦截与响应拦截
虽然 jQuery Ajax 没有原生的 “拦截器”,但可通过重写$.ajaxSetup()实现全局拦截:
javascript
运行
// 全局请求拦截:统一添加请求头、loading状态 $.ajaxSetup({ beforeSend: function(xhr) { // 1. 显示loading弹窗 $('.loading').show(); // 2. 统一添加token xhr.setRequestHeader('token', sessionStorage.getItem('token')); }, complete: function() { // 请求完成(成功/失败)隐藏loading $('.loading').hide(); } });2. 防重复提交(解决重复点击按钮的问题)
在提交表单 / 删除数据时,重复点击会导致多次请求,可通过 “锁机制” 解决:
javascript
运行
let isSubmitting = false; // 请求锁 $('.btn-submit').click(function() { if (isSubmitting) return; // 已有请求在进行,直接返回 isSubmitting = true; request({ url: '/pc/goods/add', data: $('#goods-form').serialize(), success: function() { alert('添加成功'); }, error: function() { // 错误也需要释放锁 isSubmitting = false; }, complete: function() { // 请求完成释放锁 isSubmitting = false; } }); });3. 取消请求(解决页面跳转后请求仍在进行的问题)
当用户快速切换页面时,未完成的请求会浪费资源,可通过abort()取消:
javascript
运行
// 存储当前请求的XHR对象 let xhr = null; function getGoodsList() { // 如果有未完成的请求,先取消 if (xhr) { xhr.abort(); } xhr = $.ajax({ url: '/pc/goods/list', success: function(res) { renderGoodsList(res.data); xhr = null; // 请求完成清空 } }); } // 页面切换时取消请求 $('.menu-item').click(function() { if (xhr) { xhr.abort(); } });4. 跨域问题处理
Ajax 请求默认受 “同源策略” 限制(协议、域名、端口需一致),后台管理系统中常见的跨域解决方案:
- 后端配置 CORS:在服务器响应头添加
Access-Control-Allow-Origin: *(或指定域名); - 前端配置代理:通过 Nginx 或 Webpack DevServer 代理请求,避免浏览器跨域检测;
- JSONP:仅适用于 GET 请求(不推荐,安全性低)。
四、Ajax 高频坑与避坑指南
| 常见问题 | 原因 | 解决方案 |
|---|---|---|
| 404 Not Found | 接口 URL 错误、路径拼接错误 | 1. 检查 URL 是否与后端一致;2. 封装统一路径前缀(如const baseUrl = '/pc');3. 用浏览器 Network 面板查看请求地址 |
| 401 Unauthorized | Token 失效 / 未携带 Token | 1. 统一在请求头携带 Token;2. 监听 401 状态码,自动跳转到登录页;3. 登录时更新 Token |
| 403 Forbidden | 权限不足 | 1. 检查用户角色与接口权限;2. 前端添加权限校验,无权限时隐藏按钮 |
| 500 Internal Server Error | 后端接口异常 | 1. 查看 Network 面板的响应内容;2. 配合后端排查接口逻辑;3. 前端添加错误提示,避免白屏 |
| 异步回调地狱 | 多层请求嵌套(如先查分类,再查商品) | 1. 用 Promise 封装 Ajax,配合async/await;2. 避免多层嵌套,拆分独立函数 |
| 参数传递失败 | POST 请求参数格式错误 | 1. 确认contentType:表单格式用application/x-www-form-urlencoded,JSON 格式用application/json;2. 复杂参数用JSON.stringify()转换 |
五、Ajax vs Fetch vs Axios:该怎么选?
| 特性 | Ajax(jQuery) | Fetch API | Axios |
|---|---|---|---|
| 兼容性 | 好(支持 IE6+) | 差(IE 不支持) | 中(需 polyfill) |
| 易用性 | 高(封装完善) | 中(原生 API,需手动处理解析) | 高(Promise 封装,拦截器) |
| 功能 | 基础(无拦截器、取消请求需手动处理) | 基础(需封装) | 丰富(拦截器、取消请求、超时处理) |
| 适用场景 | 传统后台系统、老项目 | 现代前端项目(React/Vue) | 中大型前端项目 |
建议:
- 老项目(如基于 jQuery 的后台管理系统):继续使用 jQuery Ajax,封装通用函数即可;
- 新项目(React/Vue):优先使用 Axios(功能丰富,生态完善);
- 轻量场景:可使用 Fetch API(无需引入第三方库)。
六、总结
Ajax 作为前端异步请求的核心技术,其本质是XMLHttpRequest的封装与应用。在后台管理系统等实战场景中,掌握以下核心要点即可打造高可靠的请求体系:
- 封装通用请求函数:统一处理 Token、错误、返回格式,减少重复代码;
- 全局拦截与状态管理:通过
beforeSend/complete处理 loading、权限校验; - 避坑核心:用 Network 面板排查请求错误,处理跨域、Token 失效、重复提交等问题;
- 技术选型:老项目用 jQuery Ajax,新项目用 Axios,轻量场景用 Fetch。
掌握 Ajax 的原理与实战技巧,不仅能解决日常开发中的请求问题,更能理解前端与后端通信的核心逻辑 —— 这也是前端工程师从 “会用” 到 “精通” 的关键一步。
关键点回顾
- jQuery Ajax 是对原生 XHR 的封装,核心优势是简化配置、兼容性好,适合传统后台系统;
- 封装通用请求函数可统一处理 Token、错误、返回格式,是项目提效的核心手段;
- 实战中需重点解决重复提交、Token 失效、跨域、路径错误等高频问题;
- 技术选型需结合项目场景,老项目用 jQuery Ajax,新项目优先 Axios。
编辑分享
博客中加入一些关于Ajax的历史发展和未来趋势的内容
写一篇关于Ajax的博客需要参考哪些资料?
分享一些关于Ajax的最佳实践和案例
编程
极速获取专业代码解答,或 @ 唤起常用语