XMLHttpRequest vs Fetch API:一场跨越时代的“浏览器宫斗剧“

 

## 序幕:两个API的"身世之谜"

在Web开发的江湖里,XMLHttpRequest(简称XHR)就像一位身经百战的老将,而Fetch API则是手持光剑的绝地武士。让我们先来段"DNA检测":

- **XHR(2006出道)**  
  "AJAX的初恋对象"  
  特点:事件驱动、回调地狱种子选手、自带进度监控

- **Fetch(2015登场)**  
  "Promise的模范生"  
  特点:基于Promise、流式处理专家、CORS配置达人

举个栗子🌰:当你想从服务器获取猫猫图片时
```javascript
// XHR写法(古典派)
const xhr = new XMLHttpRequest();
xhr.open('GET', '/cats');
xhr.onload = () => {
  if (xhr.status === 200) {
    console.log(JSON.parse(xhr.responseText));
  }
};
xhr.send();

// Fetch写法(现代派)
fetch('/cats')
  .then(response => response.json())
  .then(cats => console.log(cats));
```

## 第一幕:核心机制大揭秘

### 1.1 底层传输的"内功心法"
XHR的"经脉运行图":
```
[初始化] → [配置请求] → [发送] → [onreadystatechange]  
→ [状态检测] → [数据处理]
```

Fetch的"真气循环":
```
[Request对象] → [fetch发起] → [Promise链]  
→ [Stream处理] → [数据转换]
```

### 1.2 错误处理的"求生指南"
XHR的错误处理像扫雷游戏:
```javascript
xhr.onerror = () => {
  console.log('你的网络比蜗牛还慢!');
};
xhr.ontimeout = () => {
  console.log('服务器去火星旅游了?');
};
```

Fetch的错误处理像闯关游戏:
```javascript
fetch('/api')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .catch(error => {
    console.log(`捕获到野生错误: ${error}`);
  });
```

## 第二幕:六大实战场景终极PK

### 2.1 大文件上传进度条
XHR的"专属技能":
```javascript
xhr.upload.onprogress = (e) => {
  const percent = (e.loaded / e.total) * 100;
  console.log(`上传进度:${percent}%`);
};
```

Fetch的"黑科技"(通过ReadableStream):
```javascript
const controller = new AbortController();
fetch('/upload', {
  method: 'POST',
  body: new ReadableStream({
    start(controller) {
      // 流式写入数据
    }
  }),
  signal: controller.signal
});
```

### 2.2 请求超时控制
XHR的"定时炸弹":
```javascript
xhr.timeout = 5000; // 5秒定时器
xhr.ontimeout = () => {
  console.log('请求超时,请检查你的网络!');
};
```

Fetch的"组合技":
```javascript
const timeoutPromise = new Promise((_, reject) => {
  setTimeout(() => reject(new Error('请求超时')), 5000);
});

Promise.race([
  fetch('/api'),
  timeoutPromise
]).then(/*...*/);
```

## 第三幕:你不知道的高级玩法

### 3.1 请求缓存策略
XHR的"手动挡模式":
```javascript
xhr.open('GET', '/data', true);
xhr.setRequestHeader('Cache-Control', 'max-age=3600');
```

Fetch的"自动驾驶模式":
```javascript
fetch('/data', {
  cache: 'force-cache' // 可选值:default/no-store/reload/force-cache
});
```

### 3.2 跨域请求的"安全卫士"
XHR的复杂配置:
```javascript
xhr.withCredentials = true; // 携带cookie
```

Fetch的优雅处理:
```javascript
fetch('/api', {
  credentials: 'include', // 可选值: omit/same-origin/include
  mode: 'cors'
});
```

## 第四幕:性能优化秘籍

### 4.1 内存管理对比
| 操作          | XHR内存占用 | Fetch内存占用 |
|---------------|-------------|---------------|
| 10MB文件下载  | 10MB        | 流式处理≈2MB  |
| 1000并发请求  | 高          | 低            |
| 长轮询        | 一般        | 优秀          |

### 4.2 调试技巧宝典
**XHR调试三连:**
1. 在Chrome开发者工具勾选"Log XMLHttpRequests"
2. 使用xhr.addEventListener('readystatechange', debug)
3. 检查readyState的4个阶段

**Fetch调试三式:**
1. 在控制台使用`await fetch(...)`直接查看响应
2. 使用`response.clone()`防止流被消费
3. 配合`navigator.onLine`检测网络状态

## 第五幕:未来战场预测

### 5.1 即将到来的新特性
- **Fetch的"超级进化"**  
  ```javascript
  // 实验性功能:优先级设置
  fetch('/critical-data', {
    priority: 'high' // low/auto/high
  });

  // 请求保持活跃
  fetch('/keepalive', {
    keepalive: true
  });
  ```

### 5.2 终极选择指南
| 场景                 | 推荐API       | 理由                          |
|----------------------|---------------|-------------------------------|
| 文件上传进度显示     | XMLHttpRequest | 原生支持上传进度事件          |
| REST API调用         | Fetch         | 简洁的Promise链式调用         |
| 需要取消的请求       | Fetch         | 配合AbortController更优雅     |
| 兼容IE11             | XMLHttpRequest | Fetch需要polyfill             |

## 终章:开发者生存指南

当你在深夜加班时:
- 遇到老项目维护 → 拥抱XHR的兼容性
- 开发新功能 → 投入Fetch的怀抱
- 需要流式处理 → 选择Fetch的ReadableStream
- 要取消请求 → 使用AbortController

最后记住:没有最好的API,只有最合适的场景。就像你不能用瑞士军刀砍树,也不能用电锯开红酒瓶——选对工具才是王道!

**彩蛋:** 试试在控制台输入这个魔法代码,查看浏览器对两种API的支持情况:
```javascript
console.log('XHR支持度:', !!window.XMLHttpRequest);
console.log('Fetch支持度:', !!window.fetch);
```

**如果这篇指南让你少加了一天班,记得点赞关注!下期预告:《WebSocket与SSE:实时通信的冰与火之歌》**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Loving_enjoy

感谢亲们的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值