AJAX 小白角度 完全解析 +实习/面试实用性+fetch vs axios 深度对比

130 阅读9分钟

AJAX 小白完全解析


一、先理解"同步"有多难受

没有 AJAX 的时候(传统网页)

你在淘宝看商品详情
        ↓
点"查看评价"按钮
        ↓
❌ 整个页面白屏 → 转圈加载 → 全新页面出现
        ↓
你刚才滚动到的位置没了

图片重新加载

页面闪了一下

每次交互都要刷新整个页面,用户体验极差。


二、AJAX 带来的改变

你在淘宝看商品详情
        ↓
点"查看评价"按钮
        ↓
✅ 页面不动,只有"评价区域"悄悄更新
        ↓
其他部分完全不受影响

你滚动到哪还在哪

局部更新,页面不刷新——这就是 AJAX 的核心价值。


三、生活类比:餐厅点餐

传统方式(没有 AJAX)

code复制

你坐在座位上
        ↓
起身走到厨房门口
        ↓
站着等厨师做完
        ↓
端着菜走回座位
        ↓
才能继续吃饭

问题:你人走了,座位空了,回来位置可能没了。

AJAX 方式

你坐在座位上
        ↓
按铃叫服务员(JS 发请求)
        ↓
你继续吃饭、聊天、刷手机(页面不卡)
        ↓
服务员把菜端过来(数据回来了)
        ↓
你继续吃,完全没中断

关键:你不用站起来等,服务员(AJAX)在后台帮你搞定。


四、技术层面:AJAX 到底是什么

AJAX = Asynchronous JavaScript and XML

拆解:
  A → Asynchronous(异步)→ 不等结果,先干别的
  J → JavaScript        → 用 JS 代码发请求
  A → And               →
  X → XML               → 数据格式(现在基本用 JSON)

虽然名字里有 XML,但现在 99% 的场景用 JSON,所以你可以理解为 AJAJ(Asynchronous JavaScript and JSON)。


五、代码层面:怎么实现的

最原始的方式:XMLHttpRequest

js

// 1. 创建一个"服务员"对象
const xhr = new XMLHttpRequest();

// 2. 配置请求:用什么方法、去哪拿数据
xhr.open('GET', 'https://api.example.com/user/123', true);
//         方法      URL地址                    是否异步

// 3. 告诉服务员:拿到数据后告诉我
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 数据回来了!
    const data = JSON.parse(xhr.responseText);
    console.log(data.name);  // "小明"
  }
};

// 4. 发送请求
xhr.send();

现代方式:fetch(更简洁)

js

fetch('https://api.example.com/user/123')
  .then(response => response.json())  // 把响应转成 JSON
  .then(data => {
    console.log(data.name);  // "小明"
    // 更新页面某个部分
    document.getElementById('username').textContent = data.name;
  });

更现代的方式:async/await(最像人话)

js

async function getUser() {
  const response = await fetch('https://api.example.com/user/123');
  const data = await response.json();
  
  console.log(data.name);  // "小明"
  document.getElementById('username').textContent = data.name;
}

getUser();

六、AJAX 的工作流程(图解)

code

用户点击按钮
    │
    ▼
┌─────────────────┐
│  JavaScript     │  ← 拦截点击事件,不刷新页面
│  创建请求对象    │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  发送 HTTP 请求  │  ← 悄悄发给服务器(用户无感知)
│  (异步!)      │
└────────┬────────┘
         │
         ▼
    用户继续操作页面
    (滚动、点击、输入...)
    页面完全不受影响 ✅
         │
         ▼
┌─────────────────┐
│  服务器处理请求  │  ← 查数据库、算数据...
│  返回数据       │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  JavaScript 收到 │
│  数据,更新 DOM  │  ← 只改需要变的部分
│  (局部更新)    │
└─────────────────┘

七、为什么叫"异步"?

同步(Synchronous):排队等

js

// 同步代码:一行一行执行,上一行没完,下一行不跑

const result = fetchData();  // ← 卡在这里,等服务器返回

console.log(result);          // ← 这行等上面完了才执行

// 页面卡住了,用户点不了按钮

异步(Asynchronous):先干别的

js

// 异步代码:发完请求继续往下走,不等待

fetch('https://api.example.com/data')
  .then(data => {
    // 数据回来了再执行这里
    console.log(data);
  });

console.log('这行先执行');  // ← 这行不等上面,立刻执行

// 页面不卡,用户随便操作

八、实际应用场景

场景没有 AJAX有 AJAX
微博加载更多点击 → 整页刷新点击 → 底部追加新内容
购物车加减点击 → 整页刷新点击 → 数字变一下
搜索建议输入完回车 → 新页面输入中实时显示建议
点赞点击 → 整页刷新点击 → 心变红,数字+1
表单验证提交后才知道错输完立刻提示错误

九、一句话总结

AJAX

Asynchronous JavaScript and XML 异步 JS 和 XML 技术, 是前后端 沟通的一种重要机制。

AJAX 就是:用 JavaScript 在后台悄悄跟服务器说话,拿到数据后只更新页面的一小部分,不用刷新整个页面。

核心就三个词:异步、无刷新、局部更新。🤐

XMLHttpRequest vs fetch + 实习/面试实用性


一、两者特征对比

特征XMLHttpRequest (XHR)fetch
API 风格事件驱动(onload, onerror, onreadystatechange)基于 Promise(.then().catch())
代码量较多(5-6 行起步)简洁(1-2 行)
进度监控✅ 原生支持(onprogress)⚠️ 需要 ReadableStream
同步请求✅ 支持(不推荐)❌ 不支持
取消请求✅ 支持(xhr.abort())⚠️ 需要 AbortController
IE 兼容✅ IE7+❌ IE 不支持
现代项目使用率极少( legacy 代码)绝对主流

二、实习中怎么写?【仅个人所了解到的一些见解】

现实情况

code

现代前端项目:
  ├── 90% 用 fetch 或 axios(axios 底层也是 XHR,但封装好了)
  ├── 5%  用 XMLHttpRequest(老项目维护、特殊需求)
  └── 5%  其他(WebSocket、GraphQL 客户端等)

实习中你可能会看到的

js

// ✅ 现代写法(你实习大概率写这个)
const res = await fetch('/api/users');
const data = await res.json();

// 或者更常见的——用 axios(公司项目基本都用这个)
import axios from 'axios';
const { data } = await axios.get('/api/users');

js

// ❌ 实习中几乎不会手写这个(除非维护 5 年前的老代码)
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/users', true);
xhr.onreadystatechange = function() { ... };
xhr.send();

三、AI 能生成,还要学吗?

直接回答:要学,而且必须学透

原因 1:AI 生成的东西会错,你得能看出来

js

// AI 可能生成这样(有 bug)
fetch('/api/login', {
  method: 'POST',
  
  body: { username: 'admin', password: '123' }  // ❌ body 必须是字符串!
})


// 你得知道正确的是:
body: JSON.stringify({ username: 'admin', password: '123' })

原因 2:报错了你得会修

code

TypeError: Failed to fetch
CORS error
404 Not Found
500 Internal Server Error

AI 不会帮你调网络、看浏览器 Network 面板、抓包分析。这些调试能力只能靠你自己。

原因 3:面试不问"怎么写",问"为什么"

code

面试官不会问:"请手写一个 fetch 请求"
面试官会问:
  - "fetch 和 axios 有什么区别?"
  - "为什么 axios 可以拦截请求,fetch 不行?"
  - "怎么取消一个 fetch 请求?"
  - "fetch 的默认行为有什么坑?"

这些问题的答案,建立在你理解底层机制的基础上。


四、面试官到底问不问?

会问,但问法有层次

级别问题示例
基础“fetch 返回的是什么?怎么拿到 JSON 数据?”
进阶“fetch 和 XMLHttpRequest 的区别?各有什么场景?”
深入“fetch 的第二个参数可以配置什么?怎么设置超时?”
原理“axios 底层用什么实现的?为什么能支持请求/响应拦截器?”

真实面试题(了解到的一些)

code

1. fetch 和 axios 的区别?
   → axios 基于 XHR,支持拦截器、自动 JSON 转换、请求取消
   → fetch 原生 API,更轻量,但需要手动处理很多细节

2. 用 fetch 发 POST 请求要注意什么?
   → headers 里加 'Content-Type': 'application/json'
   → body 必须是 JSON.stringify() 后的字符串
   → 默认不带 cookie,需要加 credentials: 'include'

3. 怎么让 fetch 支持超时?
   → fetch 本身没有超时参数
   → 需要用 Promise.race([fetch(), timeoutPromise])

五、学习的必要性总结

code

学 XMLHttpRequest 的目的:
  └── 理解底层 HTTP 请求是怎么发出去的
  └── 知道 fetch/axios 封装了什么
  └── 遇到老项目能看懂
  └── 面试能说出"为什么"

学 fetch 的目的:
  └── 现代标准 API,所有项目都用
  └── 理解 Promise、async/await 的最佳实践
  └── 能独立写请求、处理错误、调试问题

不学 = 只会复制粘贴,报错就懵,面试被问就挂

六、找到的给实习生的一些建议

现在该学什么

code

优先级 1(必须熟):fetch + async/await + 错误处理
优先级 2(必须会):axios 的使用 + 拦截器配置
优先级 3(了解即可):XMLHttpRequest 的原理和基本用法
优先级 4(加分项):请求取消、重试机制、缓存策略

实习中实际 workflow

code

遇到要发请求的场景:
  1. 先看项目里用的什么(axios?fetch?封装的工具函数?)
  2. 复制一个已有的例子,改 URL 和参数
  3. 用 AI 辅助生成,但自己检查一遍
  4. 打开浏览器 Network 面板,确认请求发出去了、参数对了
  5. 处理错误情况(loading、失败提示)

七、一句话

AI 能帮你写代码,但不能帮你理解代码、调试代码、面试回答为什么。

学 AJAX 不是学"怎么敲",是学"HTTP 请求是怎么回事",这个底层逻辑永远有用。

面试官问的不是你记不记得 API,是你遇到问题能不能独立解决。🤐

fetch vs axios 深度对比


一、它们是什么

fetchaxios
本质浏览器原生 API第三方库(npm install axios)
底层基于 Promise 的浏览器 API基于 XMLHttpRequest
体积0(浏览器自带)~13KB(gzip 后)
兼容性现代浏览器(IE 不支持)全浏览器兼容

💡 关键认知:axios 不是 fetch 的替代品,axios 底层用的是 XMLHttpRequest,只是封装得更友好。


二、核心差异对比

1. API 风格

js

// ✅ fetch — 原生 Promise,更底层
const res = await fetch('/api/user');
const data = await res.json();  // 需要手动解析

js

// ✅ axios — 自动处理,更省事
const { data } = await axios.get('/api/user');  // 自动转 JSON

2. 错误处理(大坑!)

js

// ❌ fetch 的坑:HTTP 错误码(404/500)不会抛错!
const res = await fetch('/api/not-found');
console.log(res.ok);      // false ← 但代码没报错,继续执行
console.log(res.status);  // 404

// ✅ 需要手动判断
if (!res.ok) {
  throw new Error(`HTTP ${res.status}`);
}

js

// ✅ axios:HTTP 错误自动抛错,直接进 catch
try {
  await axios.get('/api/not-found');  // 404 → 直接抛错
} catch (err) {
  console.log(err.response.status);  // 404
}

fetch 的默认行为:只有网络错误(断网、CORS 失败)才会 reject,HTTP 4xx/5xx 都算"成功响应"。

3. 请求体处理

js

// ❌ fetch:手动 stringify,手动设 header
await fetch('/api/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ username: 'admin', password: '123' })
});

js

// ✅ axios:自动处理
await axios.post('/api/login', {
  username: 'admin',
  password: '123'
  // 自动 JSON.stringify + 自动设 Content-Type
});

4. 拦截器(axios 的核心优势)

js

// axios 请求拦截器:每个请求自动加 token
axios.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
  return config;
});

// axios 响应拦截器:统一处理错误
axios.interceptors.response.use(
  res => res,  // 成功直接过
  err => {
    if (err.response.status === 401) {
      window.location.href = '/login';  // 未登录,跳登录页
    }
    return Promise.reject(err);
  }
);

fetch 没有原生拦截器,要自己封装:

js

// fetch 实现拦截器 = 自己包一层函数
async function myFetch(url, options = {}) {
  // 请求前:加 token
  options.headers = {
    ...options.headers,
    Authorization: `Bearer ${localStorage.getItem('token')}`
  };
  
  const res = await fetch(url, options);
  
  // 响应后:统一处理
  if (res.status === 401) {
    window.location.href = '/login';
  }
  
  return res;
}

5. 请求取消

js

// ✅ axios:原生支持取消
const source = axios.CancelToken.source();

axios.get('/api/slow', {
  cancelToken: source.token
});

// 5秒后取消
setTimeout(() => source.cancel('用户取消了'), 5000);

js

// ⚠️ fetch:需要 AbortController(较新 API)
const controller = new AbortController();

fetch('/api/slow', {
  signal: controller.signal
});

// 取消
controller.abort();

6. 超时处理

js

// ❌ fetch:没有原生超时参数
// 需要自己封装
const fetchWithTimeout = (url, options = {}, timeout = 5000) => {
  return Promise.race([
    fetch(url, options),
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error('超时')), timeout)
    )
  ]);
};

js

// ✅ axios:一行配置
axios.get('/api/slow', { timeout: 5000 });

7. 进度监控(上传/下载)

js

// ✅ axios:原生支持上传/下载进度
axios.get('/api/file', {
  onDownloadProgress: (progressEvent) => {
    const percent = Math.round(
      (progressEvent.loaded * 100) / progressEvent.total
    );
    console.log(`下载进度:${percent}%`);
  }
});

js

// ⚠️ fetch:需要 ReadableStream,代码复杂很多
const res = await fetch('/api/file');
const reader = res.body.getReader();
const total = +res.headers.get('Content-Length');

let loaded = 0;
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  loaded += value.length;
  console.log(`进度:${Math.round(loaded * 100 / total)}%`);
}

三、为什么 axios 能拦截,fetch 不能?

code

axios 底层 = XMLHttpRequest(对象,可扩展)

  创建 xhr 对象 → 可以往对象上挂拦截器函数
  发请求前 → 先执行请求拦截器
  收到响应 → 先执行响应拦截器
  然后才返回给调用方

fetch 底层 = 浏览器原生 API(黑盒)

  调用 fetch() → 浏览器内部处理 → 直接返回 Promise
  你无法在"发请求前"插入逻辑
  也无法在"收到响应后"统一处理
  除非自己包一层函数

四、fetch 的默认行为坑

坑说明
不自动带 cookie需要手动加 credentials: 'include'
4xx/5xx 不抛错需要手动判断 res.ok
不自动转 JSON需要手动 res.json()
没有超时需要自己封装
没有进度需要用 ReadableStream

js

// fetch 的正确打开方式(防坑版)
async function safeFetch(url, options = {}) {
  const res = await fetch(url, {
    credentials: 'include',  // 带 cookie
    headers: {
      'Content-Type': 'application/json',
      ...options.headers
    },
    ...options
  });
  
  if (!res.ok) {
    throw new Error(`HTTP ${res.status}: ${res.statusText}`);
  }
  
  return res.json();  // 自动解析 JSON
}

五、什么时候用哪个?

场景推荐原因
简单请求、Demo、学习fetch零依赖,原生 API
企业项目、生产环境axios功能完整,生态成熟
需要进度条axios原生支持
需要拦截器统一处理axios原生支持
对包体积敏感(小程序)fetch不用额外引入
老项目维护看项目用啥保持一致

六、面试回答模板【谨供参考 具体情况具体看】

code

问:fetch 和 axios 有什么区别?

答:
1. 本质不同:fetch 是浏览器原生 API,axios 是基于 XMLHttpRequest 的第三方库
2. 功能差异:axios 有原生拦截器、自动 JSON 转换、请求取消、超时配置;fetch 这些都要自己封装
3. 错误处理:axios 对 4xx/5xx 自动抛错,fetch 只会在网络错误时抛错
4. 使用场景:简单场景用 fetch,企业项目基本用 axios
5. 底层原理:axios 基于 XHR 对象,可以在请求前后插入逻辑;fetch 是黑盒 API,无法直接拦截

总结:fetch 是"毛坯房",axios 是"精装修"。学 fetch 理解原理,用 axios 做项目。🤐