深入理解 Ajax:从原理到实战,附大厂高频面试题

一、什么是 Ajax?

Ajax(Asynchronous JavaScript and XML) 是一种在不重新加载整个页面的情况下,通过 JavaScript 异步与服务器交换数据并更新部分网页内容的技术。虽然名字中包含 XML,但现代 Ajax 更常使用 JSON 格式进行数据交互。

✅ 核心价值:提升用户体验,实现"局部刷新",避免整页跳转。


二、Ajax 的核心流程(基于 XMLHttpRequest)

XMLHttpRequest(简称 XHR)是浏览器原生提供的用于发起 HTTP 请求的 API。以下是其标准使用流程:

1. 创建请求对象

ini 复制代码
javascript
编辑
const xhr = new XMLHttpRequest();

2. 配置请求(open)

kotlin 复制代码
javascript
编辑
xhr.open(method, url, async);
// 示例:
xhr.open('GET', 'https://api.github.com/orgs/lemoncode/members', true); // 推荐异步
  • method:请求方法(GET、POST 等)
  • url:目标接口地址
  • async:是否异步(强烈建议设为 true,避免阻塞主线程)

⚠️ 注意:你的原始代码中使用了 false(同步),这会导致浏览器卡死,生产环境严禁使用同步请求

3. 设置事件监听器(onreadystatechange)

ini 复制代码
javascript
编辑
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        const data = JSON.parse(xhr.responseText);
        // 更新 DOM
    }
};

readyState 状态说明:

状态 含义
0 UNSENT 请求未初始化(刚创建)
1 OPENED open() 已调用
2 HEADERS_RECEIVED send() 已调用,响应头已接收
3 LOADING 响应体正在接收中
4 DONE 请求完成(成功或失败)

✅ 只有当 readyState === 4status === 200 时,才表示请求成功完成。

4. 发送请求(send)

scss 复制代码
javascript
编辑
xhr.send(); // GET 请求通常无参数;POST 可传 body 数据

三、完整示例修正版(推荐写法)

xml 复制代码
html
预览
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax 数据请求(修正版)</title>
</head>
<body>
    <ul id="members"></ul>
    <script>
        const xhr = new XMLHttpRequest();
        
        // 推荐:使用异步请求(async = true)
        xhr.open('GET', 'https://api.github.com/orgs/lemoncode/members', true);

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    try {
                        const members = JSON.parse(xhr.responseText);
                        document.getElementById('members').innerHTML = 
                            members.map(m => `<li>${m.login}</li>`).join('');
                    } catch (e) {
                        console.error('JSON 解析失败:', e);
                    }
                } else {
                    console.error('请求失败,状态码:', xhr.status);
                }
            }
        };

        xhr.send();
    </script>
</body>
</html>

✅ 修正点:

  • 改为 异步请求true
  • 增加 错误处理(状态码非 200、JSON 解析异常)
  • 移除冗余的 console.log,聚焦核心逻辑

四、现代替代方案:fetch API

虽然 XHR 仍广泛使用,但现代开发更推荐使用 fetch ------ 基于 Promise 的新标准:

ini 复制代码
javascript
编辑
fetch('https://api.github.com/orgs/lemoncode/members')
  .then(response => {
    if (!response.ok) throw new Error('网络响应失败');
    return response.json();
  })
  .then(members => {
    document.getElementById('members').innerHTML = 
      members.map(m => `<li>${m.login}</li>`).join('');
  })
  .catch(err => console.error('请求出错:', err));

✅ 优势:语法简洁、天然支持 Promise、更易链式调用

❌ 劣势:对 IE 不友好(需 polyfill)


五、常见问题与最佳实践

问题 解决方案
跨域请求失败 后端配置 CORS,或使用代理
同步请求卡死页面 永远不要用 async: false
JSON 解析错误 使用 try...catch 包裹 JSON.parse
内存泄漏 在 SPA 中注意取消未完成的请求(可用 AbortController)

六、大厂高频 Ajax 面试题(附答案)

1. Ajax 和 fetch 的区别是什么?

  • XMLHttpRequest 是传统 API,回调风格,需手动监听状态;
  • fetch 是基于 Promise 的现代 API,语法更简洁,但默认不处理 4xx/5xx 错误(需手动检查 response.ok);
  • fetch 不支持超时控制(需配合 AbortController),而 XHR 可通过 timeout 属性设置。

2. 为什么 Ajax 默认不能跨域?如何解决?

: 出于浏览器同源策略安全限制。解决方案包括:

  • 后端设置 CORS 头(如 Access-Control-Allow-Origin: *
  • 开发阶段使用 Webpack/Vite 代理
  • JSONP(仅限 GET,已过时)
  • Nginx 反向代理

3. 如何取消一个正在进行的 Ajax 请求?

  • XHR :调用 xhr.abort()

  • fetch :使用 AbortController

    scss 复制代码
    js
    编辑
    const controller = new AbortController();
    fetch(url, { signal: controller.signal });
    // 取消
    controller.abort();

4. Ajax 请求中,readyState 和 status 的区别?

  • readyState 表示请求生命周期阶段(0~4);
  • status 表示HTTP 响应状态码(如 200、404、500);
  • 必须同时满足 readyState === 4status === 200 才算成功。

5. 同步 Ajax 有什么问题?为什么禁止使用?

: 同步请求会阻塞浏览器主线程,导致页面"假死",用户无法交互,严重损害体验。现代浏览器已废弃同步 XHR(尤其在主线程中)。


6. 如何处理 Ajax 的错误?

  • XHR:监听 onerror 事件 + 检查 status !== 200
  • fetch:.catch() 捕获网络错误 + 检查 response.ok
  • 统一错误提示、重试机制、日志上报

七、总结

Ajax 是前端与后端通信的基石技术。掌握 XMLHttpRequest 的底层原理,有助于理解现代 fetchaxios 等封装库的设计思想。在实际开发中:

坚持异步

做好错误处理

优先使用 fetch 或 axios

理解跨域与安全机制

只有夯实基础,才能在复杂场景中游刃有余,轻松应对大厂面试挑战!


📌 延伸学习

相关推荐
梦帮科技10 小时前
GRAVIS v4.0:基于Web的极速套利架构设计与实时数据流实现
前端·人工智能·rust·自动化·区块链·智能合约·数字货币
爱勇宝10 小时前
办公资料反复修改、补传、交接混乱,我做了个桌面工具来解决这件事
前端·后端·程序员
微信开发api-视频号协议11 小时前
企业微信外部群开发自动化实践过程
java·前端·微信·自动化·企业微信·ipad
甲维斯11 小时前
Fable5:20美金的顶级设计师!
前端·人工智能
kyriewen11 小时前
我同时用了 Claude Code、Cursor 和 Codex,说说三个工具的真实差距——2026 年选错工具比不用 AI 更浪费时间
前端·ai编程·claude
Jackson__12 小时前
为了拯救我的腰椎和颈椎,我做了款浏览器插件!
前端·javascript·开源
闲猫12 小时前
Python FastAPI + SQLAlchemy 入门教程:从零搭建你的第一个 Web 应用
前端·python·fastapi
林小帅12 小时前
NestJS v11 + Prisma v7 ESM 迁移配置解析
前端·javascript·后端
IT_陈寒12 小时前
React的setState竟然不是立刻生效的,害我调试半天
前端·人工智能·后端
简简单单就是我_hehe12 小时前
前端埋点日志解决方案:完整 User-Agent 解析工具实现,爬虫识别、设备品牌、操作系统、浏览器版本全解析(附完整源码)
前端·爬虫