从 IE6 的 ActiveX 到现代浏览器的 Stream,用 1 张流程图 + 3 个真实业务案例,帮你 5 分钟选对请求方式。
一、总览:3 种请求方式对比表
维度 | XHR | Fetch | Axios |
---|---|---|---|
年代 | 2000 | 2015 | 2014 |
浏览器 | IE5+ | 现代 | 全平台 |
Promise | ❌ | ✅ | ✅ |
流/进度 | ❌ | ✅ | ✅ |
拦截器 | ❌ | ❌ | ✅ |
体积 | 0 | 0 | ~13 KB |
取消请求 | ❌ | ✅ | ✅ |
二、底层原理 30 秒速览
yaml
浏览器 → 网络层
├─ XHR: 事件驱动 (onload/onerror)
├─ Fetch: Promise 链 + Stream
└─ Axios: XHR/Fetch 封装 + Interceptor
三、3 个实战场景选型
① 老旧系统 ------ XHR 兼容 IE
js
function xhrGet(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = () => resolve(xhr.response);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}
IE9 以下唯一可行,但无取消/流。
② 现代项目 ------ Fetch + AbortController
js
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(r => r.json())
.catch(err => err.name === 'AbortError' && console.log('用户取消'));
原生 Promise,零依赖 ,可取消。
③ 企业级 ------ Axios 全家桶
js
import axios from 'axios';
const instance = axios.create({
baseURL: '/api',
timeout: 5000,
});
// 拦截器
instance.interceptors.request.use(cfg => {
cfg.headers['token'] = localStorage.token;
return cfg;
});
export default instance;
拦截器 + 取消 + 进度,开箱即用。
四、真实业务案例
场景 | 选型 | 关键代码 |
---|---|---|
上传进度条 | Fetch + ReadableStream | 见下方上传 demo |
轮询取消 | Axios + CancelToken | source.cancel('路由切换') |
SSE 实时推送 | Fetch + EventSource | new EventSource('/sse') |
五、上传进度条(Fetch 流示例)
js
async function upload(file) {
const reader = file.stream().getReader();
const body = new ReadableStream({
start(controller) {
function pump() {
reader.read().then(({ done, value }) => {
if (done) return controller.close();
controller.enqueue(value);
console.log(`已读 ${value.byteLength} 字节`);
pump();
});
}
pump();
},
});
await fetch('/upload', { method: 'POST', body });
}
六、一句话总结
XHR 保旧、Fetch 原生、Axios 万能;根据 兼容性/体积/功能 三选一,永远不用纠结。